為什么要學(xué)ios席镀?
因?yàn)椴块T要開(kāi)始進(jìn)行rn開(kāi)發(fā)了。
- 為了能在開(kāi)發(fā)前有更清晰的開(kāi)發(fā)思路夏漱,以及在開(kāi)發(fā)過(guò)程中能更好地定位問(wèn)題和解決解決
- 在閱讀rn文檔的時(shí)候豪诲,很多東西不理解,比如:
- 為什么一定要用style挂绰,而不能用css屎篱?:因?yàn)閏ssom是web特有的,native的基礎(chǔ)組件都是class葵蒂,而樣式都是考給class設(shè)置值來(lái)實(shí)現(xiàn)的交播,所以也更不用說(shuō)啥樣式的繼承啥了。
- 標(biāo)簽為什么沒(méi)有div span之類的践付,都是View Text之類的秦士?: 答案和以上,這些標(biāo)簽也是html專用的永高,而安卓ios也沒(méi)有什么dom結(jié)構(gòu)伍宦。
所以決定學(xué)習(xí)一門原聲語(yǔ)言,用iphone自然就選擇了學(xué)ios乏梁。
怎么去學(xué)?
學(xué)習(xí)語(yǔ)言
不管你準(zhǔn)備實(shí)戰(zhàn)學(xué)習(xí)关贵,還是看書(shū)學(xué)習(xí)遇骑,都得首先得看得懂代碼,而客戶端開(kāi)發(fā)都有自己的語(yǔ)言揖曾,比如ios有swift object-c落萎,而安卓有java、kotlin炭剪。我這里選擇了學(xué)習(xí)swift练链,原因之一,這是ios推薦使用的最新語(yǔ)言奴拦;其次媒鼓,他的語(yǔ)法相比oc來(lái)說(shuō),和JavaScript更相似一些。具體呢可以去看ios官方文檔绿鸣,英語(yǔ)沒(méi)那么好也可以去看swift中文文檔疚沐,這個(gè)中文文檔真的相當(dāng)可以。
山巒
想起原來(lái)學(xué)Vue的時(shí)候就是刷完了文檔潮模,然后再刷一套實(shí)戰(zhàn)視頻亮蛔,跟著視頻來(lái)一遍,基本上就可以算是入門了擎厢。再深入就只有持續(xù)開(kāi)發(fā)來(lái)更熟悉來(lái)更累積經(jīng)驗(yàn)了究流。這次學(xué)習(xí)ios也本打算這么搞,但是我真的沒(méi)有找到質(zhì)量好的實(shí)戰(zhàn)視頻动遭。最終選擇了看書(shū)芬探,最后買了《ios開(kāi)發(fā)指南》。
學(xué)習(xí)筆記
首先你需要安裝Xcode沽损,app store直接下載即可灯节。
我這里的版本是:Version 11.3.1 。
基礎(chǔ)
ios 原生UI開(kāi)發(fā)方式目前主要有兩種绵估,一種就是故事板技術(shù)炎疆,文件后綴.storyboard,本質(zhì)上就是拖拽生成界面国裳,然后將界面和class關(guān)聯(lián)(目前我個(gè)人的理解:ios最常見(jiàn)的代碼單元就是一個(gè)類形入,一個(gè)UI視圖也是一個(gè)類,所以在你拖拽生成的一個(gè)界面中缝左,你想指定按鈕點(diǎn)擊事件等亿遂,就需要將這個(gè)頁(yè)面和一個(gè)ViewController進(jìn)行管理):
另外一種UI開(kāi)發(fā)方式就是我們常見(jiàn)的代碼來(lái)描述UI結(jié)構(gòu)了,但是剛剛我們說(shuō)了視圖上的每個(gè)元素也都是一個(gè)類渺杉,所以在描述UI結(jié)構(gòu)也是new一個(gè)class蛇数,聲明長(zhǎng)寬高等一堆屬性,然后把它加入到視圖中:
他們并沒(méi)有像html一樣的結(jié)構(gòu)描述語(yǔ)言是越。這也是看rn教程 沒(méi)有所謂
div
span
之類元素的原因耳舅。如果你用過(guò)一些canvas的庫(kù),你會(huì)發(fā)現(xiàn)這樣的寫(xiě)法很那些很像倚评,非常的原始浦徊,對(duì)于用慣了什么Vue React的人來(lái)說(shuō),這肯定寫(xiě)起來(lái)很累天梧,并且效率很低(也是會(huì)出現(xiàn)rn的誘因之一吧盔性?)。
注意:swift new一個(gè)類不需要關(guān)鍵字new呢岗。
創(chuàng)建項(xiàng)目
右上角 file -> new -> project -> single view app:
主要看Language和User interface冕香,語(yǔ)言我們肯定選擇Swift蛹尝,然后就是UI,如果你想感受一下故事板技術(shù)暂筝,這里就選storyboard箩言,如果不想用故事板,那么就直接選擇Swift焕襟,純代碼構(gòu)建陨收。 如果不小心創(chuàng)建了storyboard那么可以重建一個(gè)項(xiàng)目,或者搜索 如何刪除main.storyboard鸵赖,網(wǎng)上會(huì)有一堆教程(因?yàn)樵瓉?lái)的xcode版本默認(rèn)創(chuàng)建的項(xiàng)目都是帶main.storyboad的务漩,所以網(wǎng)上有一堆教你怎么刪除這個(gè)東西,用純代碼進(jìn)行編程的)它褪。最后三項(xiàng)對(duì)于入門來(lái)說(shuō)暫時(shí)也用不到饵骨,直接不選就好了。第一項(xiàng)是是否用數(shù)據(jù)庫(kù)(mobile phone本身就是一臺(tái)儲(chǔ)存比較小的計(jì)算機(jī)而已茫打,所以是可以直接支持?jǐn)?shù)據(jù)庫(kù)的)居触,后兩項(xiàng)是單元測(cè)試、UI測(cè)試老赤,如果選了其實(shí)就是在工程中會(huì)新增一些文件或者組轮洋。
目錄結(jié)構(gòu)
- AppDelegate:是應(yīng)用程序的委托對(duì)象,繼承了UIResponder類抬旺,實(shí)現(xiàn)了UIApplicationDelegate委托協(xié)議弊予。簡(jiǎn)單來(lái)說(shuō)就是操作App一系列生命周期的地方。(協(xié)議之后會(huì)講到)
- SceneDelegate:ios13之后新加的分屏設(shè)計(jì)开财。原來(lái)沒(méi)有這個(gè)文件汉柒,初始化根視圖的操作之類的都在AppDelegate那個(gè)文件里寫(xiě),但是新增的這個(gè)文件承擔(dān)了部分它的功能责鳍,現(xiàn)在轉(zhuǎn)而都在這里寫(xiě)了碾褂。(也有人閑大多數(shù)程序都不支持場(chǎng)景,所以會(huì)直接刪除這個(gè)文件)
- ViewController:根視圖的控制器历葛,我們來(lái)寫(xiě)一個(gè)程序的第一個(gè)頁(yè)面代碼就都是在這里寫(xiě)的正塌。
- Main.storyboard 和 LaunchScreen.storyboard:都是故事板,原來(lái)只有一個(gè)故事板啃洋,就是整個(gè)程序的UI設(shè)計(jì),而現(xiàn)在新增了LaunchScreen屎鳍,是加載app時(shí)宏娄,出現(xiàn)的屏幕UI設(shè)計(jì)。如果創(chuàng)建項(xiàng)目時(shí)User interface沒(méi)有選storyboard就不會(huì)有Main那個(gè)文件逮壁,但是LaunchScreen還會(huì)保留孵坚。
- Assets.xcassets:防治各種資源文件的目錄。
- info.plist:項(xiàng)目的各種配置,對(duì)應(yīng)到前端的node項(xiàng)目的話有點(diǎn)package.json的感覺(jué)卖宠。且plist這個(gè)文件后綴巍杈,用其他編輯器打開(kāi),實(shí)際上是一個(gè)xml文件扛伍。
應(yīng)用的生命周期
ios應(yīng)用有5種狀態(tài):
- Not running(非運(yùn)行狀態(tài)):應(yīng)用沒(méi)有運(yùn)行或者被系統(tǒng)終止筷畦。
- Inactive(前臺(tái)非活動(dòng)狀態(tài)):應(yīng)用正在進(jìn)入前臺(tái)狀態(tài),但是還不能接受事件處理刺洒。
- Active(前臺(tái)活動(dòng)狀態(tài)):應(yīng)用進(jìn)入前臺(tái)狀態(tài)鳖宾,能夠接受事件處理。
- Background(后臺(tái)狀態(tài)):應(yīng)用進(jìn)入后臺(tái)后逆航,依然能夠執(zhí)行代碼鼎文。如果有可執(zhí)行的代碼就會(huì)執(zhí)行,如果沒(méi)有或者執(zhí)行完了就會(huì)進(jìn)入掛起狀態(tài)因俐。
- Suspended(掛起狀態(tài)):進(jìn)入一種冷凍狀態(tài)拇惋,不能執(zhí)行代碼,如果系統(tǒng)內(nèi)存不夠了就會(huì)被終止抹剩。
在狀態(tài)進(jìn)行躍遷的過(guò)程中應(yīng)用會(huì)進(jìn)行一些回調(diào)和一些本地通知:
方法 | 本地通知 | 說(shuō)明 |
---|---|---|
application:didFinishLaunchingWithOptions: |
UIApplicationDidFinishLaunchingNotification |
應(yīng)用初始化時(shí)會(huì)調(diào)用該方法并發(fā)出通知撑帖,會(huì)實(shí)例化根視圖控制器 |
applicationDidBecomeActive: |
UIApplicationDidBecomeActiveNotification |
應(yīng)用進(jìn)入前臺(tái)并處于活動(dòng)狀態(tài)時(shí)調(diào)用該方法,可以恢復(fù)UI吧兔。 |
applicationWillResignActive: |
UIApplicationWillResignNotification |
從活動(dòng)狀態(tài)進(jìn)入到非活動(dòng)狀態(tài)調(diào)用該方法磷仰。保存UI狀態(tài)。 |
applicationDidEnterBackground: |
UIApplicationDidEnterBackgroundNotification |
進(jìn)入后臺(tái)時(shí)調(diào)用該方法境蔼,可以保存用戶數(shù)據(jù)灶平,釋放一些資源。 |
applicationWillEnterForeground: |
UIApplicationWillEnterForegroundNotification |
進(jìn)入到前臺(tái)時(shí)箍土,但是沒(méi)有處于活動(dòng)狀態(tài)逢享,可以恢復(fù)用戶數(shù)據(jù)。 |
applicationWillTerminate: |
UIApplicationWillTerminateNotification |
應(yīng)用被終止吴藻,可以釋放資源瞒爬,保存用戶數(shù)據(jù)。 |
一些場(chǎng)景
- 點(diǎn)擊圖標(biāo)進(jìn)入沟堡,或者程序被終止后進(jìn)入:Not running -> Inactive -> Active (依次觸發(fā):
application:didFinishLaunchingWithOptions:
侧但、applicationDidBecomeActive:
) - 點(diǎn)擊Home鍵,應(yīng)用退出場(chǎng)景:
- 應(yīng)用掛起:Active -> Inactive -> Background -> Suspended (依次觸發(fā):
applicationWillResignActive:
航罗、applicationDidEnterBackground:
禀横,Inactive -> Background 不觸發(fā)) - 不掛起(根據(jù)info.plist配置):Active -> Inactive -> Background -> Suspended -> Not running(比起上面 Suspended -> Not running多觸發(fā)一個(gè):
applicationWillTerminate:
)
- 應(yīng)用掛起:Active -> Inactive -> Background -> Suspended (依次觸發(fā):
- 掛起重新運(yùn)行:Suspended -> Background -> Inactive -> Active(Suspended -> Background不觸發(fā),依次觸發(fā)
applicationWillEnterForeground:
粥血、applicationDidBecomeActive:
) - 應(yīng)用終止(在后臺(tái)的應(yīng)用因?yàn)閮?nèi)存不足而被終止):Background -> Suspended -> Not running (內(nèi)存清除場(chǎng)景下不會(huì)調(diào)用任何方法和通知)柏锄。
目標(biāo)
剛剛我們提到了plist里可以設(shè)置酿箭,程序切后臺(tái)時(shí)掛起還是不掛起,這就是一個(gè)產(chǎn)品屬性趾娃。而產(chǎn)品和目標(biāo)直接相關(guān)缭嫡,目標(biāo)和工程本身又息息相關(guān)。
我們?cè)趂ile -> new -> target菜單里選single view page抬闷,可以新建一個(gè)目標(biāo):
最后一個(gè)Project選項(xiàng)就是目標(biāo)關(guān)聯(lián)的工程妇蛀,點(diǎn)擊finish就生成了一個(gè)目標(biāo):
目標(biāo)包含一套完整的文件,且獨(dú)立于原來(lái)的test存在饶氏。
想要運(yùn)行哪個(gè)目標(biāo)讥耗,就在目標(biāo)中進(jìn)行選擇:
這其實(shí)就是一個(gè)方案(Schema),方案指一個(gè)要編譯執(zhí)行的目標(biāo)疹启,包括一系列配置信息古程,一個(gè)xcode可以包含n個(gè)方案。
產(chǎn)品屬性
當(dāng)我們點(diǎn)擊每個(gè)target的根目錄時(shí)喊崖,就會(huì)出現(xiàn)一系列選項(xiàng):
我們常常根據(jù)產(chǎn)品需要來(lái)進(jìn)行設(shè)置挣磨,比如屏幕方向、設(shè)備支持的情況這些常規(guī)信息荤懂,也有編譯鏈接的庫(kù)等信息茁裙。
ios運(yùn)行原理
Main Run Loop
一個(gè)iOS應(yīng)用程序的main run loop主要作用是處理所有與用戶相關(guān)的事件须肆。UIApplication對(duì)象在啟動(dòng)時(shí)就設(shè)置main run loop和使用它來(lái)處理事件和更新基于view的界面拆宛。正如它名字所示,main run loop是運(yùn)行在應(yīng)用程序的主線程勾习。這樣就確保與接收到用戶相關(guān)的事件被有序地處理廊宪。
下圖顯示main run loop的架構(gòu)和用戶事件最終是怎樣被應(yīng)用程序處理矾瘾。當(dāng)用戶與設(shè)備交互時(shí),系統(tǒng)就會(huì)生成與交互關(guān)聯(lián)的事件箭启,然后被應(yīng)用程序的UIKit通過(guò)一個(gè)特殊的端口來(lái)分發(fā)壕翩。應(yīng)用程序把事件放入隊(duì)列,然后逐個(gè)分發(fā)到main run loop來(lái)執(zhí)行傅寡。UIApplication
對(duì)象是第一個(gè)對(duì)象接收到事件放妈,然后決定怎樣處理它。一個(gè)touch event通常都被分發(fā)到main window對(duì)象荐操,然后依次分發(fā)到發(fā)生觸碰的view芜抒。其他event的接收事件對(duì)象路徑可能有點(diǎn)不同。
關(guān)鍵對(duì)象
UIApplication對(duì)象
用戶與iOS設(shè)備交互時(shí)產(chǎn)生的事件(Multitouch Events托启,Motion Event宅倒,Remote Control Event)交由UIApplication
對(duì)象來(lái)分發(fā)給control objects(UIControl)對(duì)應(yīng)的target objects來(lái)處理并且管理整個(gè)事件循環(huán),而一些關(guān)于app運(yùn)行時(shí)重要事件委托給app delegate
來(lái)處理驾中。App delegate對(duì)象
App delegate
對(duì)象遵循UIApplicationDelegate
協(xié)議唉堪,響應(yīng)app運(yùn)行時(shí)重要事件(app啟動(dòng)、app內(nèi)存不足肩民、app終止唠亚、切換到另一個(gè)app、切回app)持痰,主要用于app在啟動(dòng)時(shí)初始化一些重要數(shù)據(jù)結(jié)構(gòu)灶搜;例如,初始化UIWindow
工窍,設(shè)置一些屬性割卖,為window添加rootViewController
。View controller對(duì)象
View Controller
有一個(gè)view
屬性是view層次結(jié)構(gòu)中的根view患雏,你可以添加子view來(lái)構(gòu)建復(fù)雜的view鹏溯;controller有一些viewDidLoad
、viewWillAppear
等方法來(lái)管理view的生命周期淹仑;由于它繼承UIResponder
丙挽,所有還會(huì)響應(yīng)和處理用戶事件。Documents和data model對(duì)象
data model對(duì)象主要用來(lái)存儲(chǔ)數(shù)據(jù)匀借。例如颜阐,餓了么app在搜索切換地址后,有歷史記錄搜索地址歷史吓肋,當(dāng)app下次啟動(dòng)時(shí)凳怨,讀取和顯示搜索地址歷史。
document對(duì)象(繼承UIDocument)用來(lái)管理一些或所有的data model對(duì)象是鬼。document對(duì)象并不是必須的肤舞,但提供一種方便的方式來(lái)分組屬于單個(gè)文件或多個(gè)文件的數(shù)據(jù)。UIWindow對(duì)象
UIWindow
對(duì)象位于view層次結(jié)構(gòu)中的最頂層屑咳,它充當(dāng)一個(gè)基本容器而不顯示內(nèi)容萨赁,如果想顯示內(nèi)容,添加一個(gè)content view到window兆龙。
它也是繼承UIResponder
杖爽,所以它也是會(huì)響應(yīng)和處理用戶事件。View紫皇、control慰安、layer對(duì)象
View
對(duì)象可以通過(guò)addSubview和removeFromSuperview 等方法管理view的層次結(jié)構(gòu),使用layoutIfNeeded和setNeedsLayout等方法布局view的層次結(jié)構(gòu)聪铺,當(dāng)你發(fā)現(xiàn)系統(tǒng)提供view已經(jīng)滿足不了你想要的外觀需求時(shí)化焕,可以重寫(xiě)drawRect方法或通過(guò)layer屬性來(lái)構(gòu)造復(fù)雜的圖形外觀和動(dòng)畫(huà)。還有一點(diǎn)铃剔,UIView也是繼承UIResponder撒桨,所以也能夠處理用戶事件查刻。
Control
對(duì)象通常就是處理特定類型用戶交互的View,常用的有button凤类、switch穗泵、text field等。
除了使用View
和Control
來(lái)構(gòu)建view層次結(jié)構(gòu)來(lái)影響app外觀之外谜疤,還可以使用Core Animation框架的Layer
對(duì)象來(lái)渲染view外觀和構(gòu)建復(fù)雜的動(dòng)畫(huà)佃延。
MVC
iOS應(yīng)用程序都遵循Model-View-Controller的架構(gòu),Model負(fù)責(zé)存儲(chǔ)數(shù)據(jù)和處理業(yè)務(wù)邏輯夷磕,View負(fù)責(zé)顯示數(shù)據(jù)和與用戶交互履肃,Controller是兩者的中介,協(xié)調(diào)Model和View相互協(xié)作坐桩。
- 當(dāng)View與用戶交互產(chǎn)生事件時(shí)尺棋,使用target-action方式來(lái)處理
- 當(dāng)View需要處理一些特殊UI邏輯或獲取數(shù)據(jù)源時(shí),通過(guò)delegate或data source方式交給Controller來(lái)處理
- Model不能直接與Controller通信绵跷,當(dāng)Model有數(shù)據(jù)更新時(shí)陡鹃,可以通過(guò)Notification或KVO (Key Value Observing)來(lái)通知Controller更新View
ios api
ios整體分為四層:
- Cocoa Touch層:提供一些基本服務(wù):多線程、觸摸輸入推送等和關(guān)鍵框架:UIKit抖坪、WatchKit等
- Media層:提供了圖形音頻等技術(shù)
- Core Services層:提供基本服務(wù)萍鲸,不提供界面:CloudKit、HealthKit等擦俐,應(yīng)用購(gòu)買脊阴,SQLite數(shù)據(jù)庫(kù)和XML等技術(shù)
- Core OS層:提供硬件和網(wǎng)絡(luò)相關(guān)的低級(jí)服務(wù)。
如何查看文檔蚯瞧?
點(diǎn)擊內(nèi)置的函數(shù)名嘿期,點(diǎn)擊問(wèn)號(hào)就會(huì)出現(xiàn)該api的簡(jiǎn)介,如果想查看更詳細(xì)的api信息就可以點(diǎn)擊Open in Developer document 查看更多:
感想:
ios的開(kāi)發(fā)是集成在一起的埋合,無(wú)論創(chuàng)建文件备徐,寫(xiě)代碼,更改配置甚颂。而不像web項(xiàng)目一樣蜜猾,只有文件,所有的配置振诬,也都是基于我們寫(xiě)的json等東西蹭睡,想要改什么也直接修改文件,添加文件即可赶么。 而在xcode里肩豁,比如我新加一個(gè)swift文件,我直接把文件復(fù)制到文件夾里是沒(méi)有用的,必須經(jīng)過(guò)xcode來(lái)添加這些文件(因?yàn)閍pp 是一個(gè)bundle清钥,而所有的路徑管理也就是基于bundle這個(gè)對(duì)象)琼锋。其次ios修改了什么,想要看見(jiàn)效果都必須重新編譯祟昭,沒(méi)有所謂熱更新之類的東西斩例。
ios大概框架就是這個(gè)樣子 以后再介紹學(xué)習(xí)了的更詳細(xì)的內(nèi)容。
參考
- iOS應(yīng)用程序的生命周期
- 《ios指南》