讓不懂編程的人愛上iPhone開發系列2 iOS12+Swift4.2版-Checklists-07

說明

本系列教程改編自raywenderlich.com中的iOS Apprentice系列,有需要的童鞋請移步到這裡購買英文版原教程:store.raywenderlich.com

歡迎繼續我們的學習。

在上一課的內容中,我們成功的在界面中添加了一個表視圖,然後讓它顯示了幾行數據信息。不過看起來是完全相同的,都是佔位文字」Label「。

接下來讓我們稍微做點調整,起碼讓每一行顯示的內容都不同吧。

將行數據添加到cell中

在Xcode中打開storyboard?文件,然後選擇table view cell中的標籤label。如果你怕選擇錯了,可以在左側的視圖元素列表中點擊選擇。

然後在Xcode右側的?面板中切換到Attributes Inspector,將Tag這一欄的數值設定為1000.

設置這樣?個tag(標記)究竟有神?用處呢?通過tag標記我們可以給?用戶界?中的視覺元素設置一個 數字標識符,這樣在後續需要使用到它的時候可以很容易找到。那麼這?為神?要設置為1000呢? 其實沒神?特別道理,只要這個數字不是0就行(因為0是標記的默認數值)。如果你願意,?你最習慣的1024也可以,你懂的~

注意:

?定要確定你的標記值是設置在標籤上。初學者最常犯的錯誤就是給table view cell設置了標記值,?不是給Label標籤設置。這樣最後的結果就不是你所期待的了。

接下來在Xcode中打開ChecklistViewController.swift,更改tableView(_:cellForRowAt:)

方法的代碼如下:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
//添加下面的代碼
let label = cell.viewWithTag(1000) as! UILabel

if indexPath.row == 0 {
label.text = "流浪地球"
} else if indexPath.row == 1{
label.text = "瘋狂的外星人"
} else if indexPath.row == 2{
label.text = "飛馳人生"
} else if indexPath.row == 3{
label.text = "喜劇之王"
}else if indexPath.row == 4{
label.text = "小豬佩奇過大年"
}
//結束以上的新代碼段
return cell
}

在這個?法體中,第?行代碼我們之前已經了解過了,它的作?就是獲取prototype cell的拷貝(不 管是新的還是回收利用的),然後把它賦予新創建的一個cell本地變數,其類型是

UITableViewCell。 接下來的就是新東西了,?先是這??:

let label = cell.viewWithTag(1000) as! UILabel

這?我們請求獲取cell中的標記為1000的?視圖,這個標記就是我們剛才在storyboard中在標籤上所設置的。通過這種方法,我們就獲取了?個到該UILabel標籤對象的引?。 實際上,通過使?tag標記的?式來獲取到某個視覺元素的引?用是?常方便的,可以省掉了聲明 @IBOutlet變數的步驟。

思考:

好吧,為神?這?我們不在視圖控制器中添加?個IBOutlet屬性聲明,然後把cell的標籤和 storyboard中的outlet關聯在?起呢?

答案:

在table視圖中可能不??個cell,?而個cell都會擁有?己的標籤。如果我們使用之前的?法,將prototype cell中的標籤和視圖控制器中的某個outlet關聯在?起,那麼該屬性只能指向其中?個cell的標籤,?不是所有。

需要注意的是,label標籤屬於cell的?視圖,?不是屬於視圖控制器,因此我們不能為它創建?個outlet。聽到這句話是不是有點糊塗?Don』t panic!不要恐慌~

在後續的教程中我們將繼續回到這個話題,但在這?就暫時別管了。

到底什麼是indexPath呢?

在上一課的內容中,我們教過大家一個小小的技巧。當你在Xcode的源代碼中看到某個方法、參數或屬性之前從來沒見過時,可以按下option鍵,然後點擊關鍵詞查看。

這個大概解釋下indexPath的作用。

簡單來說,它是指向表中某個特定行的對象。當表視圖為cell請求數據源的時候,程序會查看indexPath.row的?編號屬性,從 ?確定該cell需要哪?行數據。

在使?表視圖的時候,我們還有可能把不同的?放進section?面。?如在地址薄應用中,我們會使?姓來查找聯繫?人。所有姓以A開頭的聯繫?人會被分到同?個section組中,?所有姓以B開頭的聯繫人會被放到另?個section組中,以此類推。 為了查找某?行所屬的section,我們需要使?indexPath.section屬性。因為Checklists應?用不會?到這種分組方式,所以可以暫時忽略NSIndexPath的section屬性。

繼續回到代碼。

接下來的?行代碼應該不會讓你很頭大。

if indexPath.row == 0 {
label.text = 「觀看《流浪地球》」
} else if indexPath.row == 1{
label.text = 「觀看《瘋狂的外星人》」
} else if indexPath.row == 2{
label.text = 「觀看《飛馳人生》」
} else if indexPath.row == 3{
label.text = 「觀看《喜劇之王》」
}else if indexPath.row == 4{
label.text = 「觀看《小豬佩奇過大年》」
}

之前我們已經學過if- else if -else的語法結構。這?程序檢查了indexPath.row的屬性值,其中包含了行編號,然後根據不同的?編號賦予標籤中的?本不同的值。

在這裡,我們列出了2019年春節賀歲檔要看的幾部熱門電影,作為重要的待辦事項~

作為一個鐵杆的科幻迷,當然是首推《流浪地球》了。

當然,要吐槽一下的是,《三體》究竟什麼時候可以拍出來呢?

需要特別注意的是,第?行的index屬性值是0,?不是1。

在程序世界裡,萬物從0開始。所有如果你的列表中有四個事項,那麼它們的編號是0,1,2和3。當然 這個有點反?人類,畢竟我們習慣了數??的?指1,2,3,4。不過在程序世界?面就是這樣的。因 此,對於第?個section中的第?行,indexPath.row的值是0,?indexPath.section的值也是0.第?行的編號是1,第三行的編號是2,以此類推。

其實萬物從0開始也是符合陰陽太極理論的。?子?過:「道?一,?生?,?生三,三?萬物。」 這?的道可以看做0。

萬物負陰?抱陽,沖?以為和。0和1構成了變幻?窮的程序世界,豈不對應了陰陽?

當然,以上只是瞎掰,不要當真。

好了,現在可以運?應用,看看我們有哪些事情要做的~

可以看到,現在我們的時間管理軟體顯示了5件事情,也就是我們要看的5部賀歲片~

現在讓我們回顧一下如何使用tableView(_:cellForRowAt:) 為表視圖提供數據。

首先,我們需要獲取一個UITableViewCell對象。

然後,根據indexPath的行編號來更改cell中的內容。

小練習:

如果你閑得無聊,打算把這5部賀歲片反反覆復看個幾十遍。那麼,現在可以嘗試著往表視圖中填充100行數據。

1.把tableView(_:numberOfRowsInSection:) 方法的返回值設置為100.

2.更改剛才所添加的設置label.text的相關代碼如下:

if indexPath.row % 5 == 0 {
label.text = "觀看《流浪地球》"
} else if indexPath.row % 5 == 1{
label.text = "觀看《瘋狂的外星人》"
} else if indexPath.row % 5 == 2{
label.text = "觀看《飛馳人生》"
} else if indexPath.row % 5 == 3{
label.text = "觀看《喜劇之王》"
}else if indexPath.row % 5 == 4{
label.text = "觀看《小豬佩奇過大年》"
}

這?用到了模操作符 %,如果你的中?學數學還沒忘光光的話,可能對它還有?分印象。模操作其實就是返回除法計算的餘數。?如13 %4 =1,因為13除以4的結果是3.25,?整數來表示的話除法的結果是3,然後餘數是1.?12%4=0,因為沒有餘數。

這樣?來,第1?,第6?,第11?,第16?,等等都會顯示」觀看《流浪地球》」,第 2?行,第7?,第12?,等等都會顯?"觀看《瘋狂的外星人》」,以此類推。

想來你已經很清楚,每隔5?所顯示的?本內容都會再次重複。這?我們會顯示100?內容,如果你要搞上??堆普通的if-else if -else也可以,但顯然我們可以使?模操作來簡化這個過程。

第?行: 0%5 = 0

第?行: 1%5 =1

第三行: 2%5 =2

第四行: 3%5 =3

第五行: 4%5 =4

第六行: 5%5 =0 (和第?行相同,從這裡開始所顯示的內容會開始循環)

第七?: 6%5 =1(和第??相同)

第?行: 7%5 =2(和第三行相同)

第九行: 8%5 = 3(和第四?相同)

第?行: 9%5 = 4 (和第五行相同)

第?一?: 10%5 =0(和第?行相同,再次循環之前的內容) 第?二行: 11%5 =1 (和第?行相同)

。。。。。。 後?就不再折騰了,相信你百分百可以看懂了。

假如你還是看不懂,也沒關係,只要知道這?我們?了?個?小的技巧快速填滿了整個表。 運?應?,可以看到類似下?的界?:

小技巧:

如果你是在模擬器上進行測試,那麼可以按下滑鼠左鍵,然後上下拖動,就跟在真機上使用手指拖動一樣~但是如果不按下滑鼠左鍵,是沒辦法拖動的。

思考:

為了顯示這100行數據,我們?到了多少個table view cell呢?

答案:

100個?

錯!

顯而易見,100行數據,難道不是用100個cell嗎?

遺憾的是人類的直覺往往有誤導性,雖然我們有100?數據,但在屏幕上最多同時可以容納14個cell。

等等,哥剛才仔細數了數,不是只有13個cell嗎?沒錯,如果表中的內容靜?,的確我們只看到13 個cell,但如果你上下滾動表視圖,會發現有時上?的cell還在顯?,?新的cell已經在底部出現了。 因此?少需要14個cell。

如果你滾動表視圖的速度?夠快,或許可能表視圖需要更多的臨時cell,這?點我不確定。不過這?點重要嗎?不重要嗎?是的,不重要。你只需要表視圖會替你完成這個任務就?了。我們要做的事情是,當表視圖需要?個cell的時候向它提供,同時?相應行的數據信息來填滿這個cell就好了。

總之,通常來說所需要的cell比row要少。因為如果我們的應用為每一行數據都提供一個cell,iOS很快就會榨乾了iPhone或iPad的內存,哪怕你是最新最NB的可以秒殺MBP的iPad Pro也不行。哪怕你有成千上萬條數據,我們在屏幕上需要查看的永遠也就那麼幾條十幾條而已,否則整個程序立馬就崩了~

現在可能你已經明白了為什麼UITableView表視圖把row和cell分的這麼請,row代表著數據,可能有成千上萬條甚至更多。而cell則是屏幕上可視化的部分,最多也就那麼十來條而已。

奇怪的崩潰

很多童鞋在通過郵件、私信或者論壇提問的時候,都會提到同樣的一個問題:」為什麼我照著你的內容一步步操作,但是程序還是崩潰了?到底哪裡出了問題?「

在開發的過程中,有無數種原因可能導致程序崩潰。

而其中一種就是你可能無意中在代碼中設置了一個breakpoint(斷點)。

斷點其實是個好東西,它可以幫助我們對代碼進行調試。使用斷點的方式是在源代碼的某一行或某幾行添加斷點,然後跳轉到Xcode的調試器。當斷點發揮作用的時候,給你的感覺跟程序崩潰是一樣的,但實際上程序只是暫停而已。

下面我們看一看斷點到底是長什麼樣的。

如果你的應用突然崩潰了,然後源代碼的某一行上面出現了藍色的箭頭,那麼Don』t panic,你只是」觸發「了一個斷點而已。

有些時候我們會為了調試的需要而設置斷點,但還有些時候是因為不小心誤操作而已,我也曾經犯過類似的錯誤~

移除斷點其實很簡單,只要按下滑鼠左鍵,把它向左拖出Xcode窗口就好了。

當然,還有一種方式就是點擊這個斷點,那麼它會從藍色變成灰色。斷點仍然存在,只不過會暫停發揮作用。

好了,一下子學了這麼多,我們也該休息一下了。

我們下一課再見~

聯繫方式:

個人微信: iseedo

微信公眾號:icodefun

答疑說明:

大家後續有開發相關的問題請到課程答疑專區提問icode.fun/ask/forum.php

接下來當然是福利時刻了~


推薦閱讀:

TAG:iOS開發 | iPhone | 蘋果公司(AppleInc.) |