學習 iOS App 開發,其實是段折磨人的過程,不斷地遭遇問題,然後再不斷地解決問題。因為它,讓我終於明白古人說的,不經一番寒徹骨,焉得梅花撲鼻香的道理。所謂的高手或大大,其實不是因為他們從不犯錯,而是他們早已遇過千百個問題,花了許多時間解決問題。因此他們在開發 App 時,比較少犯錯。遇到問題時,因為有了之前的經驗,也能很快解決,讓你覺得他是神,不是人。
彼得潘由於開發 iOS App 和教學的原因,自己經歷了很多問題,也看到許多初學者和朋友在學習時遇到的問題,受到的折磨。因此我計畫整理天底下所有 iOS App 開發的問題,方便大家之後遇到問題時三秒找到解答。(大家都知道,Google 其實不是很好找答案,stack overflow 又是滿滿的英文)
凡事總要有個開始,現在,就讓我們打開第一集的 iOS App 開發常見技術問題精選集,先從初學者容易遇到的問題開始解題 !
App 啟動後,會先顯示一兩秒鐘的開頭畫面,接著再顯示被箭頭指到的 controller 畫面。
經由控制箭頭指到的 controller,我們可以決定誰是第一個畫面。但是,倘若如下圖所示,你不小心讓箭頭不見了,將會發生很可怕的事情 !
問題 1:storyboard 裡指定第一個畫面 controller 的箭頭不見了 !
App 啟動後,使用者將看到一片漆黑的黑色畫面,什麼都不能做,只能心裡偷偷對著 App 開發者 os: “不懂你的黑色幽默,我要給你留下一顆星的負評 ! ”
在 storyboard 裡點選想成為第一個畫面的 controller,在它的 Attributes Inspector 頁面勾選 Is Initial View Controller,即可讓箭頭再度現身 !
問題 2:outlet 或 action 找不到連線目標,造成 App 閃退
開發 iOS App 時,我們一般會將程式和 App 畫面分開,然後利用 outlet 存取控制 storyboard 畫面上的元件,利用 action 設定事件發生時觸發的 function。(比方點選按鈕)
因此,outlet 和 action 十分偉大,幫助我們串聯 storyboard 和程式兩個不同的世界。但是如果你不小心把 outlet 連結的變數或 action 連結的 function 刪除時,原本的連線還是會在,造成 App 啟動後找不到連結的目標,引發 App 閃退的悲劇。
結果:
App 閃退,Xcode 顯示類似以下的畫面。
其實 Xcode 有點明白又不太明白地告訴我們錯誤的原因,線索就藏在右下角顯示錯誤訊息的 Console 裡。比較值得閱讀的是以 Terminating app due to uncaught exception 開頭的那段文字:
*** Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[<lovepoem.viewcontroller 0x7fb798c03480=””> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key peterPanButton.'</lovepoem.viewcontroller>
以後當你看到錯誤訊息提到 “this class is not key value coding-compliant for the key” 時,十之八九都是因為 outlet 找不到連結的變數。而且它還會當抓耙子,告訴我們凶手是誰。比方剛剛的例子,它提到了 peterPanButton,表示曾經有個 outlet 連到 peterPanButton,但是現在程式碼裡找不到 peterPanButton !
如果是 action 找不到連結的 function,錯誤訊息則會類似這樣
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[LovePoem.ViewController butPress:]: unrecognized selector sent to instance 0x7fa078504000’
關鍵字在 unrecognized selector,表示它找不到 function,而且它也會跟我們說 function 的名字,比方剛剛例子裡的 butPress:。
以彼得潘自己的教學經驗,初學者如果發現 App 一啟動就閃退,或是顯示某個頁面,點選某個按鈕時閃退,大概有六成以上的機率是 outlet 或 action 找不到連線目標導致。(因為你們還不會寫太進階的功能,所以還用不著擔心是你寫的某段複雜程式碼造成的。) 如果你還發現 Console 的錯誤訊息出現剛剛提到的關鍵字,那大概就八九不離十了。
1.在 storybard 點選造成閃退的 controller 元件。
2.從右鍵選單找尋是否有黃色警告的三角形。
如果有的話,即表示有找不到連線目標的 outlet 或 action。
3.看到黃色三角形,殺就對了。不殺它,你的 App 會閃退。殺它十分容易,點選 x 即可刪除。
以上閃退的故事告訴我們,分手要分乾淨,不要藕斷絲連,不然會很可怕。因此千萬記得當你在程式碼裡將 outlet 連結的變數或 action 連結的 function 刪除時,還要回到 storyboard 刪除當初的連線。
問題 3:在LaunchScreen.storyboard 裡設計 App 頁面
想像一個情景,你在 storyboard 裡用盡了洪荒之力,製作一頁漂亮的 App 頁面,如下圖所示,在一秒落淚情詩 App 裡顯示世界上最會寫情詩的兩個詩人,白居易和彼得潘。
App 啟動後,精心製作的畫面才顯示 2 秒鐘就消失了,畫面變成一片空白 !
Why ? Why ? Why ? 想必你此刻有種無語問蒼天的心情。
其實這都是你咎由自取呀, 因為你在錯誤的 storyboard,LaunchScreen.storyboard 裡設計 App 頁面的關係。LaunchScreen.storyboard 人如其名,老天爺讓它出生在這個世上,任務只有一個,負責顯示開頭畫面,而且只有一兩秒,過了兩秒鐘,它就只能退場,不能再留戀殘存。
甚至更慘的,如果你在 LaunchScreen.storyboard 做一些複雜的操作,比方設定 segue,將 controller 的類別設成自訂的類別,將直接產生可怕的紅色 compile error,連 App 都生成不了。
在 LaunchScreen.storyboard 以外的 storyboard 製作 App 頁面。對初學者來說,一般是 Main.storyboard。
問題 4:不小心在程式碼裡設定讓 App 停止執行的可怕中斷點。
剛學習 iOS App 開發的初學者時常會不小心按出中斷點,就好像梁朝偉的電眼不小心放電吸引女生一樣,不過不小心按出中斷點遠比不小心放電可怕多了 ! 當 App 啟動後,執行到設為中斷點的某行程式碼時,App 將暫停在某個畫面,此時無論你多大力地點擊畫面上的按鈕都不會有反應,就好像 App 已經死了一樣。
別哭,其實 App 還沒有死,它只是執行到設為中斷點的程式碼,停止了執行,就好像我們為了怕殭屍發現暫時停止呼吸一樣。
到底中斷點是怎麼不小心按出的呢 ? 如下圖所示,當點選到程式碼左邊灰色的 bar 時,將生成藍色的箭頭。凶手就是它 ! 它就是中斷點,人是它殺的,是它害 App 停止執行的。
消滅中斷點的方法很簡單,有以下兩種:
方法1:按住藍色箭頭,將它拖曳到旁邊,出現 X 圖示時放開觸碰板,藍色箭頭將化成灰燼,永遠消失在這個世界。
方法2:點擊藍色箭頭,讓它從深藍色變淺藍色。淺色的它將失去力量,再也無法讓 App 停止執行。(ps: 如果再次點擊,它將回復力量,成為讓 App 停止執行的可怕深藍色。)
問題 5:拉 outlet 和 action 的連線時,忘了切換到 Automatic。
拉 outlet 和 action 的連線,是開發 iOS App 一定要熟練的招式 ! 但是初學者時常遭遇擱淺的困境,突然之間拉不了線。常見的錯誤原因有以下兩點:
1.Assistant editor 顯示錯誤的檔案。
比方以下例子,它應該顯示控制此頁面的 ViewController,但它卻顯示無關的陌生人 AppDelegate !
2.Assistant editor 頁面顯示的檔案為不能編輯的 (Interface) 模式。
比方以下例子,ViewController.swift (Interface) 將顯示 ViewController 的屬性和方法清單,它是為了讓我們了解 ViewController 有哪些功能,並不是讓我們編輯修改的。( 有個很簡單可以辦別的方法,如果 class 前面出現 internal ,或是檔案名稱最後有(Interface),即表示目前顯示的檔案不能編輯)
解法:
點選 Assistant editor 上方 bar 裡 < > 旁的文字,將它切換成 Automatic ,如此才能聰明地自動顯示可以拉線的檔案,比方控制 storyboard 裡被選取頁面的 controller 檔案。
問題 6:storyboard 裡 controller 的類別忘了設成自訂的類別,造成無法拉 outlet 和 action
為了新增頁面,我們時常在 storyboard 畫布上加入新的 view controller。
它預設的類別為 iOS SDK 內建的 UIViewController。因此我們無法修改它的程式碼,也無法拉 outlet 和 action。
如果你硬要用蠻力拉 outlet 和 action 到 UIViewController,Xcode 將顯示警告視窗提醒我們,告訴我們
“UIViewController.h” is locked for editing and you may not be able to save your changes. Do you want to unlock it?
將 controller 元件的類別改成我們自訂的類別。
問題 7:新增檔案時,不小心選到 iOS 以外的種類
大部份的初學者一開始都是先學習 iOS App 的開發,之後才會學習比較進階的 watchOS,tvOS,macOS。因此你們在新增檔案時,也要記得分類要選到 iOS,如果不小心選錯,像上圖一樣選到 macOS,雖然一樣可以新增 storyboard 或繼承 UIViewController 的類別,但是生成的東西在 iOS 的世界將無法使用。
選了 macOS 下的 Cocoa Class,產生的 swift 檔將變成 import Cocoa,Cocoa 是 macOS App的函式庫,iOS App 無法使用 ! 所以 Xcode 在編譯生成 iOS App 時將馬上產生錯誤,說它不認識 Cocoa,No such module ‘Cocoa’。
記得你的心裡只有 iOS,只能選它,沒有其它人,看不到 watchOS,tvOS,macOS。
問題 8:寫程式時喜歡自己一字一字打,忘了自動完成
程式初學者有時太過沈醉於寫程式打字的快感,想要每個字都自己打,於是就忘了自動完成。雖然大家都有多年的打字經驗,小時候都得過 xxx 打字冠軍。不過程式語言是個被惡魔詛咒,極容易打錯字的語言,當你愈努力地用真心一字一字輸入時,有 99 % 機率打錯。
比方以下例子,當我們想生成 UIImage 物件,輸入 UIImage(n 後,即可從提示選單找到目標,按下 Enter 鍵自動完成輸入。
然而當你自己輸入時,你極有可能將參數打成 name,忘了加 d。
問題 9:AppIcon 的圖片尺寸不對
為了讓 iPhone 桌面顯示的 Icon 有最好的效果,Apple 強制規定我們只能提供兩種尺寸的 App Icon,120 * 120 (像素) 的適合一般的 iPhone,180 * 180 的適合 5.5 吋的 iPhone。
結果:
Apple 十分愛美,App Icon 尺寸不對時,將顯示以下錯誤訊息,連 App 都不讓我們生成。
The app icon set named “AppIcon” did not have any applicable content.
在 60pt 的 2x 格子放入 120 * 120 的圖片,3x 格子放入180 * 180 的圖片。
問題 10:App 閃退時,找不到殺人凶手。
出來混總是要還的,寫 App 也一樣,難免會寫出有問題的程式,造成 App 閃退。閃退並不可恥,只要我們可以在上架前修正,找到閃退的原因將它修正。
閃退的原因百百款,有的凶手很好找,一下子就可修正。有的則十分狡猾,花個一星期尋找卻依然毫無頭緒。其實閃退時有個很重要的線索,藏在右下角的 Console,裡頭的錯誤訊息告訴我們 App 怎麼死的。你可以學著去看懂訊息的內容,隨著經驗累積,你將能愈來愈明白它說的火星文。
而當找尋多日還是找不著,快要放棄轉行賣雞排時,也許你會想找人幫忙,比方請彼得潘幫忙。此時請將 Console 裡所有的文字用 cmd + a 複製,然後再將它傳給彼得潘,裡頭將藏有幫助彼得潘破案的珍貴線索。
當然,也會有更困難的問題,需要你將 App 的整個專案寄給彼得潘才能研究分析。不過至少剛剛 Console 的訊息可以提供初步的線索,解決簡單的問題。
以上就是彼得潘第一集 iOS App 開發常見技術問題精選集所蒐集的十個問題。我知道還有許多的問題,相信這會是個可以連載一百集,一千集的系列。也歡迎大家跟彼得潘聯絡,跟我訴苦抱怨你 App 開發時遇到的問題,也許下次你的問題就會出現在誠品排行榜第一名的 iOS App 開發問題精選集 !
如果有問題別害羞,歡迎在下面留言,或者直接和彼得潘 聯繫喔!