iOS開發的那些坑(貳)

Alchemist發表於2016-07-25

當時光流逝,記憶也開始散去,猛然回頭卻發現自己還在原地。

目前做iOS平臺開發有兩種語言,這就導致了一個專案組可能同時存在使用Swift和使用OC的開發者,這就導致了對於語言選擇的分歧。此外我相信網上大部分的程式碼塊還仍然是OC的,那麼如果純用Swift,有時候就需要把一整段的OC轉換成Swift,而重複是邪惡了。同時用過Swift的都知道,OC的那種囉嗦的語法真的很煩人。

To be or not to be, that is the question.

在開發中,我們總是會遇到這樣一種情況——我以前遇到過這個問題,可是我也不記得當時是怎麼解決的,反正肯定有solution——然後又花了一定的時間去解決這個問題。有時候我們解決了一個問題(或者繞過了一個問題),但是並沒有仔細去思考這個問題的由來與你真正的解決方法,這就會導致下次遇到它時還會跳進同一個坑。人不能兩次踏入同一條河流,卻總是不斷地踏入同一個坑。

當時光流逝,記憶也開始散去,猛然回頭卻發現自己還在原地。

No man ever steps in the same river twice, for it’s not the same river and he’s not the same man.

本文繼續接著上一篇,對開發中的一些小坑進行總結,環境仍然是OC和Swift混編,所以程式碼貼出來可能兩種語言都有。內容有:

  1. 使用git解決Xcode開發中的衝突
  2. 可滑動的頂部為tab欄的View的實現(如smzdm iOS APP首頁)
  3. 使用tableView.dequeueReusableCellWithIdentifier來初始化value1型別的cell,detailTextLabel為nil
  4. 如何一秒鐘向CoreData中存入20000條資料
  5. 如何解決Xcode在斷點處崩潰
  6. uitableviewCell的間距
  7. 如何優雅地替換back button
  8. block的使用
  9. delegate陣列正確的開啟方式

1. 使用git解決Xcode開發中的衝突

上一篇文章留下的問題,git作為一個使用如此廣泛、功能如此強大的版本管理軟體,也是Xcode預設的版本管理工具。然而,Xcode作為一個奇葩的存在,它的原始檔組織方式、xib或者storyboard檔案的結構都異常的奇葩,導致了在和git共同使用中也會有些事情讓人摸不著頭腦。

這裡並不是要講git的理念、命令列的使用、解決問題的技巧、或者fastforward的意義等,這些去git官網看就好了,這裡是一些在Xcode專案中使用git會碰到的一些坑,簡單卻很煩人。

如果你使用storyboard來組織UI,那麼團隊協作將是你的夢魘。幾乎每點開一次storyboard檔案,就能看到檔案列表裡顯示了一個「m」符號,我也是醉了,只能右鍵去discard它,所以解決方法就是,不要把需要一個以上的人修改的東西放在storyboard裡。

xcodeproject檔案是另一個讓人頭疼的東西。在Xcode裡,預設使用group來管理檔案,你會看到所有的檔案都在工程的根目錄,但是開啟了工程就看到它們回到了自己該在的地方,原因就在 xxx.xcodeproj目錄下的兩個檔案,Xcode為所有你新增的檔案都會建立一個索引,關鍵是同樣一個檔案兩次被加入工程,索引值會不同....於是如果兩個人在不斷的向工程裡邊新增檔案,經常會在merge之後發生衝突,還會發現工程也不能正常開啟了。

解決方法就是開啟這個檔案(project.pbxproj),仔細檢視你們新增或修改的檔案,然後使用git add解決衝突。偶爾解決不善,可能會導致編譯失敗,提示找不到原始檔,可是看到原始檔們好好地躺在檔案列表裡,那就表示它們的索引不見了,去build phases裡新增原始檔就好了。

2. 可滑動的頂部為tab欄的View的實現(如smzdm iOS APP首頁)

想來想去,實在想不到一個合適的名字來形容這個東西,就拿smzdm的APP首頁來舉例吧。這個實現不難,但是比較複雜,屬於寫一次以後就可以直接用的,我的原始碼在這裡:github/lkisme

實現方法是上邊一個scrollview,下邊一個scrollview,原理簡單,註釋清晰。

3. 使用tableView.dequeueReusableCellWithIdentifier來初始化value1型別的cell,detailTextLabel為nil

UITableview有太多的方法和用法了,這次就碰到一個問題,要顯示簡單的列表,左右各一個label,於是想到了古老的UITableViewCellStyle.Value1,於是寫下了下面這樣的程式碼

self.tableView?.registerClass(UITableViewCell.self, forCellReuseIdentifier: "normalCellId")

var cell = tableView.dequeueReusableCellWithIdentifier("normalCellId", forIndexPath: indexPath)
if cell == nil {
            cell = UITableViewCell(style: .Value1, reuseIdentifier: "normalCellId")
        }
cell.textLabel?.text = "XXX"
cell.textLabel?.font = UIFont.systemFontOfSize(14)
cell.textLabel?.textColor = UIColor.init(hexString: "#c5c5c5")

cell.detailTextLabel?.text = "yyy"
cell.detailTextLabel?.font = UIFont.systemFontOfSize(14)
cell.detailTextLabel?.textColor = UIColor.init(hexString: "#6a6a6a")複製程式碼

可是發現右邊的detailTextLabel怎麼都不顯示,打斷點看到cell.detailTextLabelnil,百思不得其解。一時心急,就是用let cell = UITableViewCell.init(style: UITableViewCellStyle.Value1, reuseIdentifier: nil)來作為一個workaround。 之後回過頭來看,原來是這樣的。像上邊這樣的程式碼呼叫時,由於我register了一個class給了tableview,那麼在呼叫dequeueReusableCellWithIdentifier("normalCellId", forIndexPath: indexPath)時,它就會使用UItableviewCell來生成一個物件,並不會返回nil,就不會進入下邊的初始化過程,而自動生成的這個物件預設的Style是Default。

解決方案一就是上邊說的workaround,二就是使用同樣古老的dequeueReusableCellWithIdentifier("normalCellId"),這個方法會返回nil

4. 如何一秒鐘向CoreData中存入20000條資料

思路其實很簡單,之前寫的CoreData的方法都是每插一條資料,使用context寫一次檔案,這次等全部插完(或者每500條,1000條)之後再儲存,程式碼如下:

//MARK: - 批量新增
func addSBatch(ses : SArray) -> Void {
    if (context == nil) {
        print("新增失敗,context為nil")
        return
    }
    let undoManager = context.undoManager
    context.undoManager = nil
    for s in ses {
        //建立物件
        let st = NSEntityDescription.insertNewObjectForEntityForName("S", inManagedObjectContext: context) as! S
        //物件賦值
        s.code = s.data
    }
    save()
    context.undoManager = undoManager
}複製程式碼

不使用這個方法,需要20秒插入20000條資料,使用之後只需要1秒。

5. 如何解決Xcode在斷點處崩潰

很簡單,重灌

6. uitableviewCell的間距

比如cell的高度是44,contentView的高度是33,當使用constraint時,上下左右各有8各畫素的距離。

7. 未完待續

8. 未完待續

相關文章