IOS基礎流程:Xcode開發(fā)環(huán)境

原創(chuàng):知識點總結性文章
創(chuàng)作不易蒸其,請珍惜侵歇,之后會持續(xù)更新腺毫,不斷完善
個人比較喜歡做筆記和寫總結癣疟,畢竟好記性不如爛筆頭哈哈,這些文章記錄了我的IOS成長歷程潮酒,希望能與大家一起進步
溫馨提示:由于簡書不支持目錄跳轉睛挚,大家可通過command + F 輸入目錄標題后迅速尋找到你所需要的內容

目錄

  • 一、Xcode 開發(fā)環(huán)境
    • 1急黎、Project 屬性設置
    • 2扎狱、target 屬性設置
    • 3、info 屬性設置
    • 4勃教、capabilities 屬性設置
    • 5淤击、Resource Tag 屬性設置
    • 6、build setting 屬性設置
    • 7荣回、build phase 屬性設置
    • 8遭贸、拖拽所需素材:便捷庫
  • 二、OC語言
    • 1心软、簡介
    • 2、封裝
    • 3著蛙、繼承
    • 4删铃、多態(tài)
    • 5、常用枚舉類型
  • 三踏堡、UIView
    • 1猎唁、視圖元素
    • 2、視圖跳轉
    • 3顷蟆、事件傳遞&視圖響應
    • 4诫隅、導入的框架文件
    • 5腐魂、方法和屬性
    • 6、視圖擴展
  • 四逐纬、UIViewController 的生命周期
  • 五蛔屹、NSObject
    • 1、NSObject 協(xié)議
    • 2豁生、NSObject 類的接口文件
  • 六兔毒、Swift 語言和 OC 語言對比
    • 1、聯(lián)系
    • 2甸箱、Swift 的優(yōu)點
    • 3育叁、Swift 的缺點
    • 4、細節(jié)區(qū)別
  • 七芍殖、編碼規(guī)范

一豪嗽、Xcode 開發(fā)環(huán)境

Xcode Workspace就如同工廠,Xcode Project如同車間豌骏,每個車間可以獨立于工廠來生產產品(project可獨立于workspace存在)昵骤,但是各個車間組合起來就需要工廠來組織(如果用了cocopods,就需要用workspace)肯适。Xcode Target是一條條的流水線变秦,一條流水線上面只生產一種產品。Build Settings是生產產品的秘方框舔,如果是生產汽水蹦玫,Build Settings就是其中各個原料的配方。Xcode Scheme是生產方案刘绣,包含了流水線生產樱溉,秘方,還包含生產完成之后的質檢(test)纬凤。

每個target 中的build setting參數繼承自 projectbuild settings福贞, 一旦你在target中修改任意settings來重寫project settings,那么最終生效的 settings參數以在 target 中設置的為準停士。 Project 可以包含多個target, 但是在同一時刻挖帘,只會有一個 target生效,可用 Xcode 的 scheme 來指定是哪一個 target 生效恋技。

1拇舀、Project 屬性設置

Deployment Target 部署配置

主要是對project生成的App可以運行的最低版本進行配置,默認是當前Xcode上API的最新版本,所以,在我們的項目中有需要對低版本適配的地方需要在這里設置校哎。同樣的锹雏,我們還可以在build setting中對這一屬性進行設置要拂,兩者是同步的抠璃。

Localizations 本地化

這里的功能主要是添加我們的App所支持的語言,通過上圖最下面的紅色圈內的【+】【-】按鈕可以添加或刪除不同的語種脱惰,并可以選擇根據手機的設置進行不同語種的自適應搏嗡。關于最下面的選擇是否開啟國際化,默認是開啟的枪芒。


2彻况、target 屬性設置

發(fā)布信息
  • Identify(標識符)欄:主要定義了一些和應用發(fā)布有關的標識屬性
  • Display Name(App應用顯示名):安裝到iOS手機或iPad上App的名稱
  • Bundle Identifier(包標識符):該應用的唯一ID,用來讓AppStore識別舅踪。在創(chuàng)建項目或者對象過程中Xcode就自行創(chuàng)建了包標識符纽甘,一般情況下不要修改它
  • Version(外部版本號):使用戶能夠看到的版本號
  • Build(內部版本號):開發(fā)者自己看到的版本號,以區(qū)分內部測試版本
  • Signing(簽名):主要是進行證書管理抽碌,在真機調試或者打包時我們都需要進行簽名認證才可以
部署信息
  • Deployment Target(部署對象):用來設置支持的最低版本悍赢。這個和projectinfo中的一個意思,并且货徙,這兩個的設置最好是一樣左权,如果不一樣,最后的App會以target的設置為準
  • Devices(設備):用來設置支持的設備痴颊,有iPhone赏迟、iPad和Universal三個選項。
  • Main Interface(主界面):應用啟動時預加載的主界面視圖
  • Device Orientation(設備方向):應用支持的方向蠢棱。有Portrait锌杀、Upside DownLandscape Left泻仙、Landscape Right幾種方向
應用圖標
  • Notification:通知時的圖標糕再。有應用相關的推送消息時需要顯示本應用的圖標則會顯示這個尺寸的
  • Spotlight:搜索圖標。當在Spotlight中輸入應用名玉转,搜索結果中出現(xiàn)該應用時的圖標就是這個尺寸的突想,還有設置里的圖標也是這個尺寸的
  • App:這就是正常的App圖標,安裝好之后在桌面顯示的究抓,或者分享時顯示的應用也是這個尺寸的圖標
  • App Store:應用商店中的顯示的圖標
啟動畫面
  • Luanch Image Source(啟動圖片):啟動圖片實際上定義了應用啟動后的界面猾担,一款App必須設定對應設備的啟動圖片,否則點開應用會是一片黑白
  • Luanch Screen File(啟動頁面文件):storyboard文件漩蟆,作用與Luanch Image一樣
框架
  • Embedded Binaries(綁定二進制文件):用來連接二進制文件垒探,一般在使用第三方SDK的時候使用。
  • Linked Frameworks and Libraries(鏈接的框架和庫):既可以是自帶的框架怠李,也可以是第三方框架,在Build Phases中也有類似的功能選項

3、info 屬性設置

屬性設置
  • Localization native development region : 與本地化設置有關捺癞,為默認語言
  • Executable file:程序安裝包的名稱
  • Bundle identifier:APP唯一的標識夷蚊,是根據公司的標識與項目名稱自動生成的,在上傳和測試的時候會用到
  • InfoDictionary version:版本信息
  • Bundle name:App安裝后顯示的名稱
  • Bundle OS Type code:用來標識軟件包類型
  • Bundle versions string:發(fā)布的版本字符串
  • Bundle creator OS Type code:創(chuàng)建者的標識
  • Bundle version:應用程序版本號
  • Application requires iPhone environment:用于指示程序包是否只能運行在IOS系統(tǒng)上髓介,默認為YES
  • Launch screen interface file base name:啟動界面的文件名稱
  • Main storyboard file base name:默認情況下程序的主入口
  • Supported interface orientations:設置程序默認支持的方向
權限設置
  • 麥克風權限:Privacy - Microphone Usage Description 是否允許使用你的麥克風惕鼓?
  • 相機權限: Privacy - Camera Usage Description 是否允許使用你的相機?
  • 相冊權限: Privacy - Photo Library Usage Description 是否允許訪問你的媒體資料庫唐础?
  • 通訊錄權限: Privacy - Contacts Usage Description 是否允許訪問你的通訊錄箱歧?
  • 藍牙權限:Privacy - Bluetooth Peripheral Usage Description 是否許允使用藍牙?
  • 語音轉文字權限:Privacy - Speech Recognition Usage Description 是否允許使用語音識別一膨?
  • 日歷權限:Privacy - Calendars Usage Description 是否允許使用日歷呀邢?
  • 定位權限:Privacy - Location When In Use Usage Description 我們需要通過您的地理位置信息獲取您周邊的相關數據
  • 定位權限:Privacy - Location Always Usage Description 我們需要通過您的地理位置信息獲取您周邊的相關數據

4、capabilities 屬性設置

性能設置開關選擇豹绪,例如推送通知价淌、云存儲、游戲中心瞒津、后臺模式等蝉衣。


5、Resource Tag 屬性設置

主要是為項目中的資源進行添加tag分類巷蚪,方便我們對其加載順序和加載時機進行選擇和設置病毡,即實現(xiàn)在需要的時候才加載資源。

app資源的延遲加載

app有一些只在特定情景下使用的資源屁柏,當應用可能要進入這些場景時啦膜,會請求這些資源。例如前联,在一個有很多關卡的游戲中功戚,用戶只需要當前關卡和下一關卡的資源。

不常用資源的遠程存儲

app有一些很少使用的資源似嗤,當需要這些資源時會去請求它們啸臀。例如,當app第一次打開時會展示一個教程烁落,而這個教程之后就可能不會在用到乘粒。app在第一次啟動時請求教程的資源,這之后只在需要展示教程或者添加了新功能才去請求該資源伤塌。

應用內購買資源的遠程存儲

app提供包含額外資源的應用內購買灯萍。app會在啟動完成后請求已購買模塊的資源。例如每聪,用戶在一個鍵盤app內購買了SuperGeeky表情包旦棉。應用程序會在啟動完成后請求表情包的資源齿风。

第一次啟動時必需資源的加載

app有一些資源只在第一次啟動時需要,之后的啟動不再需要绑洛。例如救斑,app有一個只在第一次啟動時展示的教程。


6真屯、build setting 屬性設置

Resolved列

最終確定的編譯方式脸候,無法自己設定,其結果是根據其右邊三欄的選擇結果以及優(yōu)先級順序來確定最后編譯時采用的編譯方式绑蔫。在圖的第二行選項卡中選擇combined選項运沦,可以直接地看到只有該欄的最后結果。

帶Target圖標列

targetbuild setting配置的編譯選項配深,可自定義携添。其優(yōu)先級最高,一旦進行設置凉馆,則最后的編譯方式以該欄的結果為準薪寓。

帶Project圖標列

projectbuild setting配置的編譯選項,可自定義澜共,這一欄的結果與projectbuild setting選項卡中的結果是一致的向叉,修改其中一個地方,另一處也會自動修改嗦董。其優(yōu)先級介于targetdefault之間母谎,當target沒有設置編譯選項,而該欄進行了設置時京革,則最后的編譯方式以該欄為準奇唤。

iOS Default列

在創(chuàng)建項目時系統(tǒng)自帶的默認編譯選項,無法修改匹摇。優(yōu)先級最低咬扇,只有當其他兩欄都沒有設置選項時,最后的編譯方式才會以該欄為準廊勃。


7懈贺、build phase 屬性設置

配置編譯器在不同編譯階段的參數,包括編譯所需的資源文件(代碼坡垫、配置以及各種資源文件)

Target Dependencies Target 對象依賴階段

某些Target可能依賴某個Target輸出的值梭灿,需要在這里設置依賴。依賴于其他target的輸出的時候冰悠,在編譯時系統(tǒng)會自動先編譯被依賴的target堡妒,得到輸出值,再編譯當前target溉卓。(比如應用擴展皮迟、插件等等)搬泥,這個階段是無法被修改的。

Compile Sources 源文件編譯階段

指定有哪些源代碼被編譯万栅,可以通過紅框中的【+】【-】按鈕進行添加或刪除資源來控制編譯的代碼文件佑钾。并且可以通過修改階段的Compiler Flags(編譯器標識)來為每個單獨文件設置其編譯器標識西疤,比如優(yōu)化設置等等烦粒。

Link Binary With Libraries 鏈接二進制庫階段

指編譯過程中會引用哪些庫文件,我們同樣可以通過【+】【-】按鈕進行添加或刪除編譯所引用的庫文件代赁。

Copy Bundle Resources 復制資源文件階段

指生成的product.app內將包含哪些資源文件扰她,同樣可以通過紅框中的【+】【-】按鈕進行添加或刪除資源來控制編譯的資源文件。該階段定義了對象中的資源文件芭碍,包括應用程序徒役、圖標、界面構造器窖壕、視頻忧勿、模板等等。這些資源都會被復制到安裝包的Contents/Resources文件夾下瞻讽。


8鸳吸、拖拽所需素材:便捷庫

當你需要創(chuàng)建 UI 界面,卻想不起視圖寫法時速勇;當你需要使用某個 Swift 語法結構晌砾,卻忘記正確拼寫時;當你需要添加圖片烦磁,卻記不清圖片名稱時养匈,都可以使用便捷庫來快速添加以上內容《嘉保快捷庫的開啟按鈕為 Xcode 頂邊欄右側的「+」按鈕呕乎。

拖拽所需素材:便捷庫

點擊后,你會發(fā)現(xiàn)便捷庫中提供五個選項陨晶,分別是「視圖Views猬仁,修改器 Modifiers,代碼段 Snippets珍逸,媒體庫 Media逐虚,顏色板 Color 」。其中視圖和修改器屬于界面搭建的范疇谆膳。代碼段包含 Swift 中常用的各種語法結構叭爱。媒體庫包含圖片等文件。顏色板則包含Assets 文件夾中自定義的所有顏色漱病。

便捷庫中所有內容均可以直接選中并拖拽至 Xcode 的編輯器面板中使用买雾。比如下面的例子把曼,我們可以從便捷庫中拖拽添加一張圖片后,再拖拽允許圖片自動調整大小的代碼漓穿。

有時你可能會覺得系統(tǒng)默認的便捷庫內容并不完全滿足你的需求嗤军,那么如何將自定義內容添加進便捷庫中呢?往便捷庫的不同選項卡中添加內容的方式稍有不同晃危。你在 Assets 里添加的圖片和顏色等內容會自動顯示在快捷庫中叙赚,無需進行任何額外操作。

若你希望將代碼段顯示在便捷庫中僚饭,可以使用鼠標選擇想要加入的代碼區(qū)域震叮,并右鍵選擇「Create Code Snippet」,效果如下圖鳍鸵。若你希望將某些部分做成占位符苇瓣,可以將占位符部分的文字用如下格式書寫 <#占位符#>,中間的占位符部分便會自動完成轉化偿乖。

自定義內容

二击罪、OC語言

1、簡介

OC語言是C 編程語言的超集贪薪,提供面向對象的功能和動態(tài)運行時媳禁。雖然消息發(fā)送同函數調用相比確實慢一點,但卻有面向對象的動態(tài)綁定優(yōu)點古掏。

面向對象的三大特性是面向對象語言的精華所在损话。面向對象是基于萬物皆對象這個哲學觀點。抽象化指的是盡可能地不考慮相關細節(jié)槽唾,只關注對象的核心和本質丧枪。類就是舍棄了每個具體對象的各種細節(jié)的模版。把一個對象抽象成類庞萍,具體上就是把一個對象的靜態(tài)特征和動態(tài)特征抽象成相應的屬性和方法拧烦,也就是把一類事物的算法和數據結構封裝在一個類之中。程序就是多個對象和互相之間的通信組成的钝计。用類創(chuàng)建對象的過程叫作實例化(instantiation )恋博,不同對象之間可以共享該類中的方法,差異就在于具體值的不同私恬。

面向對象具有封裝性债沮,繼承性,多態(tài)性本鸣。封裝隱蔽了對象內部不需要暴露給外人的細節(jié)疫衩,使得內部細節(jié)的變動跟外界不相關,只單純依靠提供的接口進行通信荣德,封裝性降低了編程的復雜度闷煤。通過繼承童芹,使得新建一個類變得更加容易,一個類從父類那里獲得其方法和屬性的工作就交給了編譯器鲤拿。多態(tài)使得不同的類所產生的對象能夠對相同的消息作出不同的反應假褪,這極大地提高了代碼的通用性〗辏總之言而生音,面向對象的三大特性大大提高了程序的重用性和可維護性。


2幕庐、三大特性

什么是封裝
  • 在程序上久锥,隱藏對象的屬性和方法實現(xiàn)細節(jié),控制在程序中屬性的讀和修改的訪問級別异剥,僅對外公開接口
  • 將數據和功能相結合,形成一個有機的整體絮重,形成“類”冤寿,其中數據和函數都是類的成員
封裝的好處
  • 過濾不合理的值
  • 屏蔽內部的賦值過程
  • 讓外部不必關注內部實現(xiàn)細節(jié)

3、繼承

  • 什么是繼承:通過繼承青伤,子類可以擁有父類中所有的成員變量和方法
  • 重寫:子類重新實現(xiàn)父類中某個方法督怜,覆蓋父類以前的做法
作用
  • 不改變原來模型的基礎上,拓展方法
  • 建立了類與類之間的聯(lián)系
  • 抽取了公共代碼
使用場合
  • 子類重寫父類方法時狠角,想保留父類方法的一些行為
  • 當兩個類擁有相同的屬性和方法時号杠,就可以將相同的東西抽取出到父類中
注意
  • 調用某個方法時,優(yōu)先去當前類中尋找丰歌,如果找不到姨蟋,再去父類中尋找
  • oc語言是單繼承,父類必須聲明在子類前面
  • 子類不能擁有和父類相同的成員變量
  • 缺點是耦合性太強立帖,刪除父類后眼溶,子類就不能夠繼續(xù)使用

4、多態(tài)

父類類型變量不能夠直接調用子類特有的方法(編譯過程會有警告)晓勇。必須強轉為子類類型便后后堂飞,才能夠直接調用子類特有的方法。

首先從多態(tài)的定義來說:用一個父類的指針指向子類的對象绑咱,在函數(方法)調用的時候可以調用到正確版本的函數(方法)绰筛。

使用多態(tài)的條件:1.子類必須重寫父類的方法。2.父類指針指向子類對象描融。

多態(tài)的使用:1. 父類的引用指向子類的對象铝噩,發(fā)送消息,調用的是子類對象的方法稼稿。2. 父類的引用指向本類的對象薄榛,發(fā)送消息讳窟,調用本類的方法。

在多態(tài)下敞恋,父類的引用可以指向子類的引用丽啡,當編譯的時候,編譯器無法確定指向的對象是什么類型硬猫,所有編譯器會將引用當做父類類型引用編譯檢查补箍。

在調用方法時,發(fā)現(xiàn)確實是子類對象啸蜜,為子類類型創(chuàng)建空間坑雅。例如:Person *p=[Student alloc] init]編譯時,會把Student 類型當成Person類型編譯衬横。[p play]運行時裹粤,調用的是Student類型的對象。在OC中蜂林,調用方法是遥诉,會檢測對象的真實類型,稱為動態(tài)綁定噪叙。

態(tài)的好處:1.提供動態(tài)綁定特性矮锈,減少不必要的程序冗余。在方法中睁蕾,把父類當成參數苞笨,使該方法具備調用所有子類同樣方法的能力,不比為每個子類都寫個方法子眶。2. 多態(tài)的出現(xiàn)提高了程序的擴展性和后期可維護型瀑凝。

// 父類的指針指向子類的對象
Tree *t1 = [[Osier alloc] init];
[t1 grow];
Tree *t2 = [[PineTree alloc] init];
[t2 grow];

輸出結果為:

柳樹在春天發(fā)芽
松樹四季常青

三、UIView

1壹店、視圖元素

  • 控件:繼承自 UIControl類橄镜,能夠響應用戶高級事件
  • 窗口:應用只有一個UIWindow對象侣集,它是所有子視圖的“根"容器
  • 容器視圖:UIScrollView的子類有UITextViewUITableViewUICollectionView,在內容超出屏幕時噪窘,它們可以提供水平或垂直滾動條
  • 顯示視圖:包括UIImageView蕾各、 UILabel褥赊、 UIProgressViewUIActivityindicatorView
  • 文本和Web視圖:包括UITextviewWKWebView, WKWebView是能夠加載和顯示 HTML代碼的視圖
  • 導航視圖:包括UITabBarUINavigationBar
屬性聲明
@property (nonatomic, strong, readonly) UILabel *title;
@property (nonatomic, strong) UIPickerView *pickerView;
@property (nonatomic, strong) UIDatePicker *datePicker;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
繼承圖

2卜朗、視圖跳轉

  • 故事板:本質上是一個XML文件,可以用來描述應用中有哪些界面点寥,界面中有哪些視圖元素艾疟,界面的布局、事件處理,以及界面之間是如何導航(或跳轉)的
  • 場景 (scene) 和過渡 (segue):一個場景中包含一個視圖控制器蔽莱,視圖控制器通過管理視圖來顯示界面弟疆。過渡定義了場景之間的導航(或跳轉)方式
  • Show Segue:在當前視圖上展示視圖,如果當前控制器是導航控制器盗冷,那么視圖的顯示會采用樹形結構導航模式怠苔;如果不是導航控制器,那么視圖顯示會采用模態(tài) (Modal) 導航模式仪糖。
  • Show Detail Segue:當采用UISplitViewController控制器時柑司, 在Detail視圖中顯示視圖。 如果在其他導航控制器中使用這個過渡锅劝,那么它和ShowSegue的效果是一樣的
  • Modal Segue:模態(tài)導航模式
  • Popover Segue:Pad設備上呈現(xiàn)浮動窗口

3攒驰、事件傳遞&視圖響應

UIView 為其提供內容以及負責處理觸摸等事件,參與響應鏈故爵,CALayer負責顯示內容contents玻粪,這是單一執(zhí)行原則。

響應者對象就是可以響應事件并對事件作出處理的對象稠集。在iOS中UIResponder類定義了響應者對象的所有方法奶段。UIApplicationUIWindow剥纷、UIViewControllerUIView以及UIKit中繼承自UIView的控件都間接或直接繼承自UIResponder類呢铆,這些類都可以當做響應者晦鞋。

響應者鏈表示一系列響應者對象組成的事件傳遞的鏈條。當確定了第一響應者后棺克,事件交由第一響應者處理悠垛,如果第一響應者不處理事件沿著響應者鏈傳遞,交給下一個響應者娜谊。一般來說确买,第一響應者是UIView對象或者UIView的子類對象,當其被觸摸后事件交由它處理纱皆,如果它不處理湾趾,事件就會交給它的UIViewController處理(如果存在),然后是它的superview父視圖對象派草,以此類推搀缠,直到頂層視圖。如果頂層視圖不處理則交給UIWindow對象處理近迁,再到UIApplication對象艺普。如果整個響應者鏈都不響應這個事件則該事件被丟棄。

第一響應者,如操作UITextField來控制鍵盤的現(xiàn)隱藏
- (BOOL)canBecomeFirstResponder
- (BOOL)becomeFirstResponder
- (BOOL)canResignFirstResponder
- (BOOL)resignFirstResponder;
- (BOOL)isFirstResponder
視圖傳遞流程
視圖傳遞流程
視圖響應流程
視圖響應流程

4歧譬、導入的框架文件

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIResponder.h>
#import <UIKit/UIInterface.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UIAppearance.h>
#import <UIKit/UIDynamicBehavior.h>
#import <UIKit/NSLayoutConstraint.h>
#import <UIKit/UITraitCollection.h>
#import <UIKit/UIFocus.h>

5岸浑、常用枚舉類型

視圖動畫曲線 UIViewAnimationCurve
/** 動畫的曲線枚舉 */
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
    UIViewAnimationCurveEaseInOut,  //!< 慢進慢出(默認值)
    UIViewAnimationCurveEaseIn,     //!< 慢進
    UIViewAnimationCurveEaseOut,    //!< 慢出
    UIViewAnimationCurveLinear,     //!< 勻速
};
視圖內容填充模式 UIViewContentMode
//!< UIView內容填充模式.
typedef NS_ENUM(NSInteger, UIViewContentMode) {
    UIViewContentModeScaleToFill,       //!< 縮放內容到合適比例大小
    UIViewContentModeScaleAspectFit,    //!< 縮放內容到合適的大小,邊界多余部分透明
    UIViewContentModeScaleAspectFill,   //!< 縮放內容填充到指定大小瑰步,邊界多余的部分省略
    UIViewContentModeRedraw,            //!< 重繪視圖邊界 (需調用 -setNeedsDisplay)
    UIViewContentModeCenter,            //!< 視圖保持等比縮放
    UIViewContentModeTop,               //!< 視圖頂部對齊
    UIViewContentModeBottom,            //!< 視圖底部對齊
    UIViewContentModeLeft,              //!< 視圖左側對齊
    UIViewContentModeRight,             //!< 視圖右側對齊
    UIViewContentModeTopLeft,           //!< 視圖左上角對齊
    UIViewContentModeTopRight,          //!< 視圖右上角對齊
    UIViewContentModeBottomLeft,        //!< 視圖左下角對齊
    UIViewContentModeBottomRight,       //!< 視圖右下角對齊
};
視圖動畫過渡效果 UIViewAnimationTransition
/** UIView動畫過渡效果 */
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,          //!< 無效果
    UIViewAnimationTransitionFlipFromLeft,  //!< 沿視圖垂直中心軸左到右移動
    UIViewAnimationTransitionFlipFromRight, //!< 沿視圖垂直中心軸右到左移動
    UIViewAnimationTransitionCurlUp,        //!< 由底部向上卷起
    UIViewAnimationTransitionCurlDown,      //!< 由頂部向下展開
};
視圖自動調整大小方式 UIViewAutoresizing
/** 自動調整大小方式 */
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,     //!< 不自動調整
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,//!< 自動調整與superView左邊的距離矢洲,保證與superView右邊的距離不變
    UIViewAutoresizingFlexibleWidth        = 1 << 1,//!< 自動調整自己的寬度,保證與superView左邊和右邊的距離不變
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,//!< 自動調整與superView的右邊距離面氓,保證與superView左邊的距離不變
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,//!< 自動調整與superView頂部的距離兵钮,保證與superView底部的距離不變
    UIViewAutoresizingFlexibleHeight       = 1 << 4,//!< 自動調整自己的高度,保證與superView頂部和底部的距離不變
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自動調整與superView底部的距離舌界,也就是說掘譬,與superView頂部的距離不變
};
視圖的動畫選項 UIViewAnimationOptions
/** UIView動畫選項 */
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0, //!< 動畫過程中保證子視圖跟隨運動
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, //!< 動畫過程中允許用戶交互
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, //!< 所有視圖從當前狀態(tài)開始運行
    UIViewAnimationOptionRepeat                    = 1 <<  3, //!< 重復運行動畫
    UIViewAnimationOptionAutoreverse               = 1 <<  4, //!< 動畫運行到結束點后仍然以動畫方式回到初始點
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, //!< 忽略嵌套動畫時間設置
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, //!< 忽略嵌套動畫速度設置
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, //!< 動畫過程中重繪視圖(注意僅僅適用于轉場動畫)
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, //!< 視圖切換時直接隱藏舊視圖、顯示新視圖呻拌,而不是將舊視圖從父視圖移除(僅僅適用于轉場動畫)
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, //!< 不繼承父動畫設置或動畫類型

    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, //!< 動畫先緩慢葱轩,然后逐漸加速
    UIViewAnimationOptionCurveEaseIn               = 1 << 16, //!< 動畫逐漸變慢
    UIViewAnimationOptionCurveEaseOut              = 2 << 16, //!< 動畫逐漸加速
    UIViewAnimationOptionCurveLinear               = 3 << 16, //!< 動畫勻速執(zhí)行,默認值

    UIViewAnimationOptionTransitionNone            = 0 << 20, //!< 沒有轉場動畫效果
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20, //!< 從左側翻轉效果
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20, //!< 從右側翻轉效果
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20, //!< 向后翻頁的動畫過渡效果
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20, //!< 向前翻頁的動畫過渡效果
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20, //!< 舊視圖溶解消失顯示下一個新視圖的效果
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20, //!< 從上方翻轉效果
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20, //!< 從底部翻轉效果

    UIViewAnimationOptionPreferredFramesPerSecondDefault     = 0 << 24, //!< 默認的幀每秒
    UIViewAnimationOptionPreferredFramesPerSecond60          = 3 << 24, //!< 60幀每秒的幀速率
    UIViewAnimationOptionPreferredFramesPerSecond30          = 7 << 24, //!< 30幀每秒的幀速率

} NS_ENUM_AVAILABLE_IOS(4_0);
視圖關鍵幀動畫選項 UIViewKeyframeAnimationOptions
typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
    UIViewKeyframeAnimationOptionLayoutSubviews            = UIViewAnimationOptionLayoutSubviews, //!< 動畫過程中保證子視圖跟隨運動
    UIViewKeyframeAnimationOptionAllowUserInteraction      = UIViewAnimationOptionAllowUserInteraction, //!< 動畫過程中允許用戶交互
    UIViewKeyframeAnimationOptionBeginFromCurrentState     = UIViewAnimationOptionBeginFromCurrentState, //!< 所有視圖從當前狀態(tài)開始運行
    UIViewKeyframeAnimationOptionRepeat                    = UIViewAnimationOptionRepeat, //!< 重復運行動畫
    UIViewKeyframeAnimationOptionAutoreverse               = UIViewAnimationOptionAutoreverse, //!< 動畫運行到結束點后仍然以動畫方式回到初始點
    UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套動畫時間設置
    UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions, //!< 不繼承父動畫設置或動畫類型

    UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 10, //!< 連續(xù)運算模式 默認
    UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 10, //!< 離散運算模式
    UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 10, //!< 均勻執(zhí)行運算模式
    UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 10, //!< 平滑運算模式
    UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10  //!< 平滑均勻運算模式
} NS_ENUM_AVAILABLE_IOS(7_0);
視圖的系統(tǒng)動畫 UISystemAnimation
typedef NS_ENUM(NSUInteger, UISystemAnimation) {
    UISystemAnimationDelete,    //!< 系統(tǒng)刪除動畫
} NS_ENUM_AVAILABLE_IOS(7_0);
視圖的外觀色調調整模式 UIViewTintAdjustmentMode
typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {
    UIViewTintAdjustmentModeAutomatic,  //!< 自動的藐握,與父視圖相同

    UIViewTintAdjustmentModeNormal,     //!< 未經修改的
    UIViewTintAdjustmentModeDimmed,     //!< 飽和靴拱、暗淡的原始色
} NS_ENUM_AVAILABLE_IOS(7_0);
語義內容屬性 UISemanticContentAttribute
typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {
    UISemanticContentAttributeUnspecified = 0,  //!< 未指定,默認值
    UISemanticContentAttributePlayback,         //!< 打開/ RW / FF等播放控制按鈕
    UISemanticContentAttributeSpatial,          //!< 控制導致某種形式的定向改變UI中,如分段控制文本對齊方式或在游戲中方向鍵
    UISemanticContentAttributeForceLeftToRight, //!< 視圖總是從左向右布局
    UISemanticContentAttributeForceRightToLeft  //!< 視圖總是從右向左布局
} NS_ENUM_AVAILABLE_IOS(9_0);
布局約束的軸 UILayoutConstraintAxis
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0,   //!< 水平約束
    UILayoutConstraintAxisVertical = 1      //!< 豎直約束
};
坐標空間協(xié)議 UICoordinateSpace
@protocol UICoordinateSpace <NSObject>

/** 將像素point由point所在視圖轉換到目標視圖view中猾普,返回在目標視圖view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 將像素point由point所在視圖轉換到目標視圖view中袜炕,返回在目標視圖view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect */
- (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 將rect從view中轉換到當前視圖中初家,返回在當前視圖中的rect */
- (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);

/** 獲取bounds */
@property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);

@end

5偎窘、方法和屬性

@class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide;

@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>

/** 返回主layer所使用的類 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) Class layerClass;
#else
+ (Class)layerClass;
#endif

@end
類方法 2個
/** 獲取視圖的方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);

/** 獲取相對于指定視圖的界面方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0);
初始化方法 2個
/** 通過Frame初始化UI對象 */
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
/** 用于xib初始化 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
屬性 8個
/** 設置用戶交互,默認YES允許用戶交互 */
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
/** 控件標記(父控件可以通過tag找到對應的子控件)溜在,默認為0 */
@property(nonatomic)                                 NSInteger tag;
/** 視圖圖層(可以用來設置圓角效果/陰影效果) */
@property(nonatomic,readonly,strong)                 CALayer  *layer;

/** 返回是否可以成為焦點, 默認NO */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);
#else
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0);
#endif
/** 是否可以被聚焦 */
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);

/** 左右滑動翻轉效果 */
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);


/** 返回即時內容的布局的方向 */
@property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0);

6陌知、視圖擴展

視圖幾何相關的擴展 UIView(UIViewGeometry)
@interface UIView(UIViewGeometry)

/** 位置和尺寸(以父控件的左上角為坐標原點(0, 0)) */
@property(nonatomic) CGRect            frame;

/** 位置和尺寸(以自己的左上角為坐標原點(0, 0)) */
@property(nonatomic) CGRect            bounds;
/** 中心點(以父控件的左上角為坐標原點(0, 0)) */
@property(nonatomic) CGPoint           center;
/** 變形屬性(平移\縮放\旋轉) */
@property(nonatomic) CGAffineTransform transform;
/** 視圖內容的縮放比例 */
@property(nonatomic) CGFloat           contentScaleFactor NS_AVAILABLE_IOS(4_0);

/** 是否支持多點觸摸,默認NO */
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED;
/** 是否獨占整個Touch事件掖肋,默認NO */
@property(nonatomic,getter=isExclusiveTouch) BOOL       exclusiveTouch __TVOS_PROHIBITED;

/** 在指定點上點擊測試指定事件 */
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
/** 判斷當前的點擊或者觸摸事件的點是否在當前的view中仆葡,默認返回YES */
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;

/** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
/** 將像素point由point所在視圖轉換到目標視圖view中志笼,返回在目標視圖view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
/** 將rect由rect所在視圖轉換到目標視圖view中沿盅,返回在目標視圖view中的rect */
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
/** 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect */
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;

/** 自動調整子視圖尺寸籽腕,默認YES則會根據autoresizingMask屬性自動調整子視圖尺寸 */
@property(nonatomic) BOOL               autoresizesSubviews;
/** 自動調整子視圖與父視圖的位置嗡呼,默認UIViewAutoresizingNone */
@property(nonatomic) UIViewAutoresizing autoresizingMask;

/** 返回“最佳”大小適合給定的大小 */
- (CGSize)sizeThatFits:(CGSize)size;
/** 調整為剛好合適子視圖大小 */
- (void)sizeToFit;

@end
視圖層次結構相關的擴展 UIView(UIViewHierarchy)
@interface UIView(UIViewHierarchy)

/** 獲取父視圖 */
@property(nullable, nonatomic,readonly) UIView       *superview;
/** 獲取所有子視圖 */
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;
/** 獲取視圖所在的Window */
@property(nullable, nonatomic,readonly) UIWindow     *window;

/** 從父視圖中移除控件 */
- (void)removeFromSuperview;
/** 插入子視圖(將子視圖插入到subviews數組中index這個位置) */
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
/** 交換subviews數組中所存放子視圖的位置 */
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;

/** 添加子視圖(新添加的視圖在subviews數組的后面, 顯示在最上面) */
- (void)addSubview:(UIView *)view;
/** 插入子視圖(將子視圖插到siblingSubview之下) */
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
/** 插入子視圖(將子視圖插到siblingSubview之上) */
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;

/** 將子視圖拉到最上面來顯示 */
- (void)bringSubviewToFront:(UIView *)view;
/** 將子視圖拉到最下面來顯示 */
- (void)sendSubviewToBack:(UIView *)view;
系統(tǒng)自動調用(留給子類去實現(xiàn))
/** 添加子視圖完成后調用 */
- (void)didAddSubview:(UIView *)subview;
/** 將要移除自視圖時調用 */
- (void)willRemoveSubview:(UIView *)subview;

/** 將要移動到新父視圖時調用 */
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
/** 移動到新父視圖完成后調用 */
- (void)didMoveToSuperview;
/** 將要移動到新Window時調用 */
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;
/** 移動到新Window完成后調用 */
- (void)didMoveToWindow;

/** 判斷view是否為子類 */
- (BOOL)isDescendantOfView:(UIView *)view;
/** 通過tag獲得對應的子視圖 */
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;

/** 對現(xiàn)在有布局有調整更改后,使用這個方法進行更新 */
- (void)setNeedsLayout;
/** 強制進行更新layout */
- (void)layoutIfNeeded;

/** 控件的frame發(fā)生改變的時候就會調用,一般在這里重寫布局子控件的位置和尺寸 */
- (void)layoutSubviews;

/** 設置view之間的間距皇耗,該屬性只對autolayout布局有效 */
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
/** 是否將當前視圖的間距和父視圖相同南窗,默認是NO */
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);
/** 改變view的layoutMargins這個屬性時,會觸發(fā)這個方法 */
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);

/** 視圖間距引導 */
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);

/** 獲取此區(qū)域的內的布局引導 */
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);
@end
視圖外觀渲染相關的擴展 UIView (UIViewRendering)
@interface UIView(UIViewRendering)

/** 重寫drawRect方法,在可以這里進行繪圖操作万伤。*/
- (void)drawRect:(CGRect)rect;

/** 標記整個視圖的邊界矩形需要重繪, 調用這個方法會自動調用drawRect方法 */
- (void)setNeedsDisplay;
/** 標記在指定區(qū)域內的視圖的邊界需要重繪, 調用這個方法會自動調用drawRect方法 */
- (void)setNeedsDisplayInRect:(CGRect)rect;

/** 是否裁剪超出Bounds范圍的子控件窒悔,默認NO */
@property(nonatomic)                 BOOL              clipsToBounds;
/** 設置背景顏色,默認nil */
@property(nullable, nonatomic,copy)  UIColor          *backgroundColor UI_APPEARANCE_SELECTOR;
/** 設置透明度(范圍0.0~1.0)敌买,默認1.0 */
@property(nonatomic)                 CGFloat           alpha;
/** 設置是否不透明简珠,默認YES不透明 */
@property(nonatomic,getter=isOpaque) BOOL              opaque;
/** 視圖重繪前是否先清理以前的內容,默認YES */
@property(nonatomic)                 BOOL              clearsContextBeforeDrawing;
/** 設置是否隱藏虹钮,默認NO不隱藏 */
@property(nonatomic,getter=isHidden) BOOL              hidden;
/** 內容顯示的模式聋庵,默認UIViewContentModeScaleToFill */
@property(nonatomic)                 UIViewContentMode contentMode;
/** 拉伸屬性,如圖片拉伸 */
@property(nonatomic)                 CGRect            contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED;

/** 蒙板view */
@property(nullable, nonatomic,strong)          UIView           *maskView NS_AVAILABLE_IOS(8_0);

/** 改變應用程序的外觀的顏色芙粱。默認為nil */
@property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);

/** 可以使tintColor變暗祭玉,因此整個視圖層次變暗 */
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);

/** 覆蓋這個方法的目的是為了當tintColor改變的時候自定義一些行為 */
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);

@end
視圖動畫相關的擴展 UIView (UIViewAnimation)
@interface UIView(UIViewAnimation)

/** 開始動畫 */
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
/** 提交動畫 */
+ (void)commitAnimations;

/** 設置動畫代理, 默認nil */
+ (void)setAnimationDelegate:(nullable id)delegate;
/** 動畫將要開始時執(zhí)行方法(必須要先設置動畫代理), 默認NULL */
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
/** 動畫已結束時執(zhí)行方法(必須要先設置動畫代理), 默認NULL */
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
/** 設置動畫時長, 默認0.2秒 */
+ (void)setAnimationDuration:(NSTimeInterval)duration;
/** 動畫延遲執(zhí)行時間, 默認0.0秒 */
+ (void)setAnimationDelay:(NSTimeInterval)delay;
/** 設置在動畫塊內部動畫屬性改變的開始時間, 默認now ([NSDate date]) */
+ (void)setAnimationStartDate:(NSDate *)startDate;
/** 設置動畫曲線, 默認UIViewAnimationCurveEaseInOut */
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
/** 動畫的重復播放次數, 默認0 */
+ (void)setAnimationRepeatCount:(float)repeatCount;
/** 設置是否自定翻轉當前的動畫效果, 默認NO */
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
/** 設置動畫從當前狀態(tài)開始播放, 默認NO */
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;

/** 在動畫塊中為視圖設置過渡動畫 */
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;

/** 設置是否激活動畫 */
+ (void)setAnimationsEnabled:(BOOL)enabled;
/** 返回一個布爾值表示動畫是否結束 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
+ (BOOL)areAnimationsEnabled;
#endif
/** 先檢查動畫當前是否啟用春畔,然后禁止動畫脱货,執(zhí)行block內的方法,最后重新啟用動畫律姨,而且這個方法不會阻塞基于CoreAnimation的動畫 */
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);

/** 當前動畫的持續(xù)時間 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif

@end
視圖用block快速定義動畫的擴展 UIView (UIViewAnimationWithBlocks)
@interface UIView(UIViewAnimationWithBlocks)

/** 用于對一個或多個視圖的改變的持續(xù)時間振峻、延時、選項動畫完成時的操作 */
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

/** 用于對一個或多個視圖的改變的持續(xù)時間择份、選項動畫完成時的操作扣孟,默認:delay = 0.0, options = 0 */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

/** 用于對一個或多個視圖的改變的持續(xù)時間內動畫完成時的操作,默認:delay = 0.0, options = 0, completion = NULL */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0);

/** 使用與物理彈簧運動相對應的定時曲線執(zhí)行視圖動畫 */
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

/** 為指定的容器視圖創(chuàng)建轉換動畫 */
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

/** 使用給定的參數在指定視圖之間創(chuàng)建轉換動畫 */
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview

/** 在一個或多個視圖上執(zhí)行指定的系統(tǒng)提供的動畫荣赶,以及定義的可選并行動畫 */
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end
視圖關鍵幀動畫相關的擴展 UIView (UIViewKeyframeAnimations)
/** UIView的關鍵幀動畫 */
@interface UIView (UIViewKeyframeAnimations)

/** 創(chuàng)建一個動畫塊對象哈打,可用于為當前視圖設置基于關鍵幀的動畫 */
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
/** 添加指定開始時間、持續(xù)時間的關鍵幀動畫(起始和持續(xù)時間是0.0和1.0之間的值) */
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);

@end
視圖上手勢相關的擴展 UIView (UIViewGestureRecognizers)
@interface UIView (UIViewGestureRecognizers)

/** 當前視圖所附加的所有手勢識別器 */
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);

/** 添加一個手勢識別器 */
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
/** 移除一個手勢識別器 */
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);

/** 開始一個手勢識別器 */
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);

@end
視圖上運動效果相關的擴展 UIView(UIViewMotionEffects)
@interface UIView (UIViewMotionEffects)

/** 添加運動效果讯壶,當傾斜設備時視圖稍微改變其位置 */
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);

/** 移除運動效果 */
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);

/** 所有添加的運動效果 */
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);

@end
視圖上安裝約束相關的擴展 UIView (UIConstraintBasedLayoutInstallingConstraints)
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)

/** 獲取所有約束 */
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);

/** 添加一個約束 */
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 添加多個約束 */
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
/** 移除一個約束 */
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 移除多個約束 */
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
@end
視圖上約束相關的擴展 UIView (UIConstraintBasedLayoutCoreMethods)
@interface UIView (UIConstraintBasedLayoutCoreMethods)

/** 更新視圖和其子視圖的約束 */
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
/** 為視圖更新約束,可以重寫這個方法來設置當前view局部的布局約束 */
- (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER;
/** 視圖的約束是否需要更新 */
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
/** 設置視圖的約束需要更新湾盗,調用這個方法伏蚊,系統(tǒng)會調用updateConstraints去更新布局 */
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);

@end
視圖上約束共存相關的擴展 UIView (UIConstraintBasedCompatibility)
@interface UIView (UIConstraintBasedCompatibility)

/** 是否啟用自動布局約束,默認YES. IB默認是NO */
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);

/** 是否使用約束布局 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#else
+ (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#endif

@end
視圖約束布局圖層相關的擴展 UIView (UIConstraintBasedLayoutLayering)
@interface UIView (UIConstraintBasedLayoutLayering)

/** 返回給定框架的視圖的對齊矩陣 */
- (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);
/** 返回給定對齊矩形的視圖的frame */
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);

/** 返回從視圖的frame上定義的對齊矩陣的邊框 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#else
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#endif

/** 返回滿足基線約束條件的視圖 */
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;

/** 返回用于滿足第一基線約束的視圖 */
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);

/** 返回用于滿足上次基線約束的視圖 */
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);


UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1
/** 返回接收對象的原本大小 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#else
- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#endif
/** 廢除視圖原本內容的size */
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0);

/** 設置當視圖要變大時格粪,視圖的壓縮改變方式躏吊,返回一個優(yōu)先權(確定view有多大的優(yōu)先級阻止自己變大) */
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 設置放先權 */
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);

/** 設置當視圖要變小時,視圖的壓縮改變方式帐萎,是水平縮小還是垂直縮小比伏,并返回一個優(yōu)先權(確定有多大的優(yōu)先級阻止自己變小) */
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 設置優(yōu)先權 */
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);

@end
視圖約束適應尺寸相關的擴展 UIView (UIConstraintBasedLayoutFittingSize)
@interface UIView (UIConstraintBasedLayoutFittingSize)
/** 返回滿足持有約束的視圖的size */
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
/** 返回滿足它所包含的約束的視圖的大小 */
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
@end
視圖布局引導相關的擴展 UIView (UILayoutGuideSupport)
@interface UIView (UILayoutGuideSupport)

/** 此視圖擁有布局向導對象的數組 */
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);

/** 向視圖中添加布局向導 */
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);

/** 向視圖中添加布局向導 */
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
@end

@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
@interface UIView (UIViewLayoutConstraintCreation)
/** 布局視圖的前緣框的布局錨點 */
@property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的后緣邊框的布局錨點 */
@property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的左邊框的布局錨點 */
@property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的右邊框的布局錨點 */
@property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的頂邊框的布局錨點 */
@property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的底邊框的布局錨點 */
@property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的寬度 */
@property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的高度 */
@property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的水平中心軸 */
@property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
/** 布局視圖的垂直中心軸 */
@property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0);
/** 一個代表對視圖中的文本的最高線基線布置錨 */
@property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0);
/** 一個代表對視圖中的文本的最低線基線布置錨 */
@property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_0);

@end
視圖約束布局調試相關的擴展 UIView (UIConstraintBasedLayoutDebugging)
@interface UIView (UIConstraintBasedLayoutDebugging)

/** 獲得實體在不同方向上所有的布局約束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);

/** 可以知道當前視圖的布局是否會有歧義 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#endif

/** 這個方法會隨機改變視圖的layout到另外一個有效的layout疆导。這樣我們就可以很清楚的看到哪一個layout導致了整體的布局約束出現(xiàn)了錯誤赁项,或者我們應該增加更多的布局約束 */
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);
@end

/** 約束調試,只在DEBUG環(huán)境下被調用 */
@interface UILayoutGuide (UIConstraintBasedLayoutDebugging)

/** 獲得實體在不同方向上所有的布局約束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0);

/** 可以知道當前視圖的布局是否會有歧義 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#endif

@end
視圖狀態(tài)保存恢復相關的擴展 UIView (UIStateRestoration)
#pragma mark - View狀態(tài)保存恢復

@interface UIView (UIStateRestoration)

/** 標示是否支持保存,恢復視圖狀態(tài)信息 */
@property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
/** 保存視圖狀態(tài)相關的信息 */
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
/** 恢復和保持視圖狀態(tài)相關信息 */
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);

@end
視圖快照相關的擴展 UIView(UISnapshotting)
#pragma mark - View快照

@interface UIView (UISnapshotting)

/** 將當前顯示的view截取成一個新的view */
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
/** 縮放一個view默認是從中心點進行縮放的 */
- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);
/** 屏幕快照 */
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);

@end

四、UIViewController 的生命周期

alloc// 創(chuàng)建對象悠菜,分配空間
init (initWithNibName)// 初始化對象舰攒,初始化數據
initWithCoder:(NSCoder *)aDecoder// 如果使用storyboard或者xib
loadView// 加載view
viewDidLoad//  載入完成,只會在APP剛開始加載的時候調用一次悔醋,所以只能用來做初始設置
viewWillAppear// 需要對數據做更新
viewDidAppear// 視圖已在屏幕上渲染完成
viewWillDisappear// 被移除覆蓋時進行善后的處理摩窃,按了Home鍵之后,APP本身仍是掛起時候的view芬骄,不調用
viewDidDisappear// 對已經消失猾愿、覆蓋、隱藏了的視圖做一些其他操作
dealloc// 視圖被銷毀账阻,此處需要對你在init和viewDidLoad中創(chuàng)建的對象進行釋放
viewWillLayoutSubviews// 多次調用布局
viewDidLayoutSubviews

五蒂秘、NSObject

字母縮寫
  • f: function 函數
  • p: parameter 參數
  • m:method 方法
  • c: class
  • v: variable 變量
NSObject.h 的結構
#include <objc/objc.h>
#include <objc/NSObjCRuntime.h>

@class NSString, NSMethodSignature, NSInvocation;

1、NSObject 協(xié)議

@protocol NSObject

/** 判斷兩個對象是否相等, 如相等返回YES, 否則返回NO */
- (BOOL)isEqual:(id)object;
/** 獲取對象hash值, 兩對象相等hash值也相等 */
@property (readonly) NSUInteger hash;

/** 獲取對象的父類 */
@property (readonly) Class superclass;
/** 獲取當前對象的類 */
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
/** 獲取當前對象 */
- (instancetype)self;

/** 發(fā)送指定的消息給對象, 返回消息執(zhí)行結果(相當于方法調用) */
- (id)performSelector:(SEL)aSelector;
/** 發(fā)送帶一個參數的消息給對象, 返回消息執(zhí)行結果(相當于方法調用) */
- (id)performSelector:(SEL)aSelector withObject:(id)object;
/** 發(fā)送帶兩個參數的消息給對象, 返回消息執(zhí)行結果(相當于方法調用) */
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

/** 判斷對象是否繼承NSObject */
- (BOOL)isProxy;

/** 判斷對象是否是給定類或給定類子類的實例 */
- (BOOL)isKindOfClass:(Class)aClass;
/** 判斷對象是否是給定類的實例 */
- (BOOL)isMemberOfClass:(Class)aClass;
/** 判斷對象是否遵從給定的協(xié)議 */
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

/** 判斷對象是否能夠調用給定的方法 */
- (BOOL)respondsToSelector:(SEL)aSelector;

/** 對象引用計數加1, 在MRC下使用 */
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
/** 對象引用計數減1, 在MRC下使用 */
- (oneway void)release OBJC_ARC_UNAVAILABLE;
/** 對象引用計數以推遲方式自動減1, 在MRC下使用 */
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
/** 獲取對象引用計數, 在MRC下使用 */
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
/** 獲取對象存儲空間, 在MRC下使用 */
- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;

/** 獲取對象描述信息 */
@property (readonly, copy) NSString *description;
@optional
/** 獲取對象在調試器中的描述信息 */
@property (readonly, copy) NSString *debugDescription;

@end

2宰僧、NSObject 類的接口文件

@interface NSObject <NSObject>  

/** 運行時加載類或分類調用該方法, 每個類只會調用一次 */
+ (void)load;
/** 類實例化使用前需要先初始化, 一個類調用一次, 如果子類沒有實現(xiàn)該方法則會調用父類方法 */
+ (void)initialize;
/** 初始化對象 */
- (instancetype)init;
 

/** 為新對象分配內存空間并初始化, 等于[[NSObject alloc] init] */
+ (instancetype)new;  
/** 為新對象分配內存空間, 參數傳nil */
+ (instancetype)allocWithZone:(struct _NSZone *)zone; 
/** 為新對象分配內存空間 */
+ (instancetype)alloc;  
/** 釋放對象, 當對象的引用計數為0時會調用此方法 */
- (void)dealloc; 
/** 垃圾回收器調用此方法前處理它所使用的內存材彪。 */
- (void)finalize;  

/** 復制為不可變對象 */
- (id)copy;
/** 復制為可變對象 */
- (id)mutableCopy;

/** 在指定的內存空間上復制為不可變對象, 在MRC下使用 */
+ (id)copyWithZone:(struct _NSZone *)zone;  
/** 在指定的內存空間上復制為可變對象, 在MRC下使用 */
+ (id)mutableCopyWithZone:(struct _NSZone *)zone;  

/** 判斷類是否能夠調用給定的方法 */
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
/** 判斷類是否遵從給定的協(xié)議 */
+ (BOOL)conformsToProtocol:(Protocol *)protocol;
/** 獲取指向方法實現(xiàn)IMP的指針 */
- (IMP)methodForSelector:(SEL)aSelector;
/** 獲取指向實例方法實現(xiàn)IMP的指針 */
+ (IMP)instanceMethodForSelector:(SEL)aSelector;
/** 找不到函數實現(xiàn)的將調用此方法拋出異常 */
- (void)doesNotRecognizeSelector:(SEL)aSelector;

/** 返回消息被第一個轉發(fā)的對象, 對象沒有找到SEL的IML時就會執(zhí)行調用該方法 */
- (id)forwardingTargetForSelector:(SEL)aSelector;  
/** methodSignatureForSelector:返回不為nil則調用該方法, 可以重寫該方法將SEL轉發(fā)給另一個對象 */
- (void)forwardInvocation:(NSInvocation *)anInvocation; 
/** 獲取方法簽名, 對象沒有找到SEL的IML時就會執(zhí)行調用該方法, 可以重寫該方法拋出一個函數的簽名,再由forwardInvocation:去執(zhí)行 */
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;

/** 獲取實例方法簽名 */
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;

/** 允許弱引用標量, 對于所有allowsWeakReference方法返回NO的類都絕對不能使用__weak修飾符 */
- (BOOL)allowsWeakReference;
/** 保留弱引用變量, 在使用__weak修飾符的變量時, 當被賦值對象的retainWeakReference方法返回NO的情況下, 該變量將使用“nil” */
- (BOOL)retainWeakReference;

/** 判斷是否是另一個類的子類 */
+ (BOOL)isSubclassOfClass:(Class)aClass;

/** 動態(tài)解析一個類方法 */
+ (BOOL)resolveClassMethod:(SEL)sel;
/** 動態(tài)解析一個實例方法, 對象沒有找到SEL的IML時就會執(zhí)行調用該方法, 可以重寫該方法給對象添加所需的SEL */
+ (BOOL)resolveInstanceMethod:(SEL)sel;

/** 獲取對象hash值, 兩對象相等hash值也相等*/
+ (NSUInteger)hash;
/** 獲取對象的父類 */
+ (Class)superclass;
/** 獲取類 */
+ (Class)class;
/** 獲取對象描述信息 */
+ (NSString *)description;
/** 獲取對象在調試器中的描述信息 */
+ (NSString *)debugDescription;

@end

六琴儿、Swift 語言和 OC 語言對比

現(xiàn)階段Swift能完全取代Objective-C嗎段化?

Apple內部一直在用Objective-C來做一些Framework的開發(fā),底層也不可能用Swift實現(xiàn)造成。

1显熏、聯(lián)系

  • SwiftObjective-C共用一套運行時環(huán)境
  • Swift的類型可以橋接到Objective-C,反之亦然
  • OC出現(xiàn)過的絕大多數概念晒屎,比如引用計數喘蟆、ARC、屬性鼓鲁、協(xié)議蕴轨、接口、初始化骇吭、擴展類橙弱、命名參數、block等燥狰,在Swift中繼續(xù)有效(最多換個術語)棘脐,當然Swift也多出了一些新興概念,比如泛型龙致、元組

2蛀缝、Swift 的優(yōu)點

  • swift是類型安全的語言,注重安全目代,OC注重靈活
  • swift注重面向協(xié)議編程屈梁、函數式編程嗤练,OC注重面向對象編程
  • swift注重值類型,OC注重指針和引用
  • swift是靜態(tài)類型語言(類型的檢查是在編譯階段做的俘闯,如C++潭苞、Java),OC是動態(tài)類型語言(類型的檢查是在運行時做的真朗,如JavaScriptPython)
  • swift容易閱讀此疹,文件結構和大部分語法簡易化,只有.swift文件遮婶,結尾不需要分號
  • swift中的可選類型蝗碎,用于所有數據類型,而不僅僅局限于類旗扑。相比于OC中的nil更加安全和簡明
  • swift中的泛型類型更加方便和通用蹦骑,而非OC中只能為集合類型添加泛型
  • swift中各種方便快捷的高階函數(函數式編程)(Swift的數組支持三個高階函數:mapfilterreduce臀防,以及map的擴展flatMap
  • swift新增了兩種權限眠菇,細化權限。open > public > internal(默認)> fileprivate > private
  • swift中獨有的元組類型(tuples)袱衷,把多個值組合成復合值捎废。元組內的值可以是任何類型,并不要求是相同類型的
  • swift支持函數式編程致燥,Objc本身是不支持的登疗,需要通過引入ReactiveCocoa這個庫才可支持函數式編程

3、Swift的缺點

  • 版本不穩(wěn)定
  • 對于不支持Swift的一些第三方類庫嫌蚤,如果非得使用辐益,只能混合編程,利用橋接文件實現(xiàn)

4脱吱、細節(jié)區(qū)別

  • 在 swift 中沒有了 main.m智政,@UIApplicationMain 是程序入口
  • swift不分.h.m文件 ,一個類只有.swift一個文件箱蝠,所以整體的文件數量比起OC有一定減少
  • swift句尾不需要分號 女仰,除非你想在一行中寫三行代碼就加分號隔開
  • 在 swift 中,一個類就是用一對 { }括起的抡锈,沒有 @implementation@end
  • swift數據類型都會自動判斷 , 只區(qū)分變量var 和常量let
  • 強制類型轉換格式不同: OC強轉:(int)a乔外, Swift強轉:Int(a)
  • 關于BOOL類型更加嚴格 床三,Swift不再是OC的非0就是真,而是true才是真杨幼,false才是假
  • swift的循環(huán)語句中必須加{}就算只有一行代碼也必須要加
  • swift的switch語句后面可以跟各種數據類型了 撇簿,如Int聂渊、字符串都行,并且里面不用寫break
  • if后的括號可以省略: if a>b {}四瘫,而OC里 if后面必須寫括號汉嗽。
  • 打印變量時可以print("(value)"),不用像OC那樣記很多%@找蜜,%d等饼暑。
  • swift的Any可以代表任何類型的值,無論是類洗做、枚舉弓叛、結構體還是任何其他Swift類型,這個對應OC中的id類型
  • 在OC中的alloc / init對應()
  • 在OC中的alloc / initWithXXX 對應 (XXX: )
  • 在 OC 中的類函數調用诚纸,在swift中撰筷,直接使用.
  • 在 swift 中,絕大多數可以省略 self.畦徘,建議一般不寫毕籽,可以提高對語境的理解(閉包時會體會到)
  • 在 OC 中的枚舉類型使用 UIButtonTypeContactAdd,而 swift 中分開了井辆,操作熱鍵:回車-> 向右 ->.
  • swift 中关筒,枚舉類型的前綴可以省略,如:.ContactAdd
  • swift中的范圍運算符更靈活掘剪。a...b 表示[a,b]包括a和b 平委。 (如3...5 就是范圍取3,4夺谁,5)廉赔。a..<b 表示 [a,b)包括a,不包括b 匾鸥。 (如3...5 就是范圍取3蜡塌,4)。常見的如for循環(huán):for i in 0...9{}

七勿负、編碼規(guī)范

原創(chuàng):知識點總結性文章
創(chuàng)作不易馏艾,請珍惜,之后會持續(xù)更新奴愉,不斷完善
個人比較喜歡做筆記和寫總結琅摩,畢竟好記性不如爛筆頭哈哈,這些文章記錄了我的IOS成長歷程锭硼,希望能與大家一起進步
溫馨提示:由于簡書不支持目錄跳轉房资,大家可通過command + F 輸入目錄標題后迅速尋找到你所需要的內容

目錄

  • 編碼規(guī)范

價值

  • 統(tǒng)一團隊書寫習慣,為效率工具提供了技術模版檀头,奠定了自動化實踐的基石
  • 根除閱讀障礙轰异,有效降低CR和輪崗成本
  • 增強了團隊和諧

變量

  • 只能以字母岖沛、數字、下劃線搭独、$組成婴削;
  • 不能以數字開頭;
  • 遵循小駝峰命名方式牙肝;
  • 不能與C語言的關鍵字重名唉俗;new copy
  • 區(qū)分大小寫;
  • 先聲明后使用惊奇;
  • 不能重復定義同名變量互躬;
@interface UCARSomeBusinessService () <SomeProtocol, OtherProtocol> {
    // 聲明一些私有變量,但不推薦颂郎;推薦使用私有屬性方式聲明
    NSString *title;
    NSInteger count;
}

屬性

// 公共屬性應該聲明在類頭文件(.h)中
@interface UCARSomeBusinessService : UCARBaseBusinessService
 
@property (nonatomic, strong) UCARSomeProperty *someProperty;
@property (nonatomic, copy) NSString *otherProperty;
 
@end
 
// 私有屬性應該聲明在類實現(xiàn)文件(.m)的延展(匿名的類目)中
@interface UCARSomeBusinessService ()
 
@property (nonatomic, strong) UCARSomeProperty *someProperty;
@property (nonatomic, copy) NSString *otherProperty;
 
@end

常量

// 常量格式:常量首選內聯(lián)字符串字面量或數字吼渡,因為常量可以輕易重用并且可以快速改變而不需要查找和替換;
// 常量應該聲明為 static 常量而不是 #define 乓序,除非非常明確地要當做宏來使用
static NSString *const viewControllerTitle = @"派單頁面";
static const CGFloat cellHeight = 66.66;

枚舉

// 枚舉格式:關鍵字寺酪、空格、換行替劈、單行注釋(居右)按如下書寫
typedef NS_ENUM(NSInteger, UCAROrderState) {
    UCAROrderState_Dispatching = 0,     // 派單中
    UCAROrderState_Dispatched  = 1,     // 派單成功
    UCAROrderState_Arrival     = 2,     // 司機已到達
    UCAROrderState_InService   = 3      // 服務中
};
 
// 當用到位掩碼時寄雀,使用 NS_OPTIONS 宏
typedef NS_OPTIONS(NSUInteger, UCARAdCategory) {
    UCARAdCategoryAutos      = 1 << 0,    // Autos
    UCARAdCategoryJobs       = 1 << 1,    // Jobs
    UCARAdCategoryRealState  = 1 << 2,    // RealState
    UCARAdCategoryTechnology = 1 << 3     // Technology
};

Method

方法定義要遵循單一原則,方法簽名不要超過100字符陨献,方法體不宜過長盒犹,方法名較短時應單行書寫
方法格式:“+/-”+空格+(返回值類型)+方法名+空格+{+換行

- (void)produceView {
    // Do something
}
 
- (UIView *)produceViewWithModel:(UCARModel *)model {
    // Do something
}
 
+ (UIView *)produceViewWithTag:(NSInteger)tag {
    // Do something
}

@protocol

@interface

Delegate盡量使用canshould眨业、will急膀、did表明回調意愿&時機;
屬性&方法添加注釋:.h文件中的注釋,必須使用 Command + / 生成的模版進行編寫
屬性&方法過多時龄捡,視情況使用 “換行” 分組

// import分組次序:Frameworks卓嫂、Services、UI
#import <SomeFramework/SomeProtocol.h>
 
@protocol UCARSomeBusinessDelegate <NSObject, UCARSomeDelegate>
@interface UCARSomeBusinessService : UCARBusinessService <UCARSomeBaseService, UCAROtherBaseService>



@required
/**
 * 屬性說明
 * @note 額外說明的注意項聘殖,說明一些需要注意的地方晨雳,沒有可取消此項。
 */
@property (nonatomic, copy) NSString *otherProperty;
@property (nonatomic, strong) UCARSomeProperty *someProperty;

/**
 * 方法說明
 * @param object 一個參數
 * @return 一個返回值
 * @note 額外說明的注意項奸腺,說明一些需要注意的地方餐禁,沒有可取消此項。
 */
- (void)shouldUpdateViewWithModel:(UCARSomeViewModel *)model;
- (void)shouldUpdateViewWithError:(NSError *)error;
- (void)willChangeDataSource;
- (void)didChangeDataSource;

@end
@implementation
@class UCARAnyProperty;
#pragma mark - 常量
#pragma mark - 枚舉

@interface UCARSomeBusinessService () <SomeProtocol, OtherProtocol> 
#pragma mark - 私有屬性
@end

@implementation UCARSomeBusinessService
 
//方法列表使用pragma分組突照,并遵守如下次序, 且# pragma mark - 與上下各添加一個空行
#pragma mark - Life cycle
 
- (void)someMethod:(UCARSomeModel *)model {
    // Do something
 
    // Block 書寫格式
    [UIView animateWithDuration:0.3 animations:^{
        // Do something
    } completion:^(BOOL finished) {
        // Do something
    }];
}
 
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters
 
@end

UIViewController

#pragma mark - Life cycle
 
- (instancetype)init {
}
 
- (void)viewDidLoad {
}
 
- (void)viewWillAppear:(BOOL)animated {
}
 
- (void)viewDidAppear:(BOOL)animated {
}
 
- (void)didReceiveMemoryWarning {
}
 
- (void)viewWillDisappear:(BOOL)animated {
}
 
- (void)viewDidDisappear:(BOOL)animated {
}
 
- (void)dealloc {
}
 
#pragma mark - Events
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - UIOtherComponentDelegate
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters

UIView

AutoLayout坠宴、Frame禁止混合使用,只能選擇一種方式1疗臁O补摹!

#pragma mark - Life cycle
 
- (instancetype)init {
}
 
- (instancetype)initWithFrame:(CGRect)frame {
}
 
- (void)updateConstraints {
}
 
- (void)layoutSubviews {
}
 
+ (BOOL)requiresConstraintBasedLayout {
    return YES;
}
 
- (void)dealloc {
}
 
#pragma mark - Events
#pragma mark - UIOtherComponentDelegate
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters

Snippets

IF/ELSE/SWITCH/FOR/WHILE語句格式:關鍵字+空格+(條件)+空格+{+換行
IF語句(如果IF語句不是方法體第一行衔肢,與上面的代碼之間添加一行空行庄岖,如果ELSE語句不是最后一行,與下面代碼之間加一行空行)

if (condition1) {
    // Do something1
} else if (condition2) {
    // Do something2
} else {
    // Do anything
}
 
 
不推薦
if (condition) return value;
if (condition)
    return value;

SWITCH語句

switch (condition) { 
    case 1: 
        // ...
        break; 
    case 2: { 
        // ... 
        // Multi-line example using braces
        break; 
    } 
    default: 
        // ...
        break; 
}

FOR語句

for (NSObject *object in list) {
    // Do something
}
 
 
for (int i = 0; i < N; i++) {
    // Do something
}

WHILE語句

while (condition) {
    // Do something
}
 
do {
    // Do something
} while (condition)

方法命名

通用命名角骤、屬性方法命名隅忿、Delegate方法命名、集合方法命名邦尊、方法參數命名背桐、私有方法命名

通用命名

1、使用小駝峰命名規(guī)則
2蝉揍、對于表示對象采取的操作的方法链峭,使用動詞開始

- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;

3、所有參數之前使用關鍵字

- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag; ?
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;                    ?

4又沾、在參數之前創(chuàng)建單詞描述參數

- (id)viewWithTag:(NSInteger)aTag;  ?
- (id)taggedView:(int)aTag;         ?

5弊仪、在創(chuàng)建比繼承方法更具體的方法時,在現(xiàn)有方法的末尾添加新關鍵字

- (id)initWithFrame:(CGRect)frameRect;  父類
- (id)initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:(Class)factoryId numberOfRows:(int)rowsHigh numberOfColumns:(int)colsWide;          子類

6杖刷、不要使用“and”來鏈接作為接收者屬性的關鍵字

- (int)runModalForDirectory:(NSString *)path file:(NSString *)name types:(NSArray *)fileTypes;          ?
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;    ?

7励饵、可以使用“and”來鏈接兩個單獨的操作

- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
屬性方法命名

1、名詞屬性格式

- (type)noun;
- (void)setNoun:(type)aNoun;
例如:
- (NSString *)title;
- (void)setTitle:(NSString *)aTitle;

2滑燃、形容詞屬性格式

- (BOOL)isAdjective;
- (void)setAdjective:(BOOL)flag;
例如:
- (BOOL)isEditable;
- (void)setEditable:(BOOL)flag;

3役听、動詞屬性格式(動詞現(xiàn)代式)

- (BOOL)verbObject;
- (void)setVerbObject:(BOOL)flag;
例如:
- (BOOL)showsAlpha;
- (void)setShowsAlpha:(BOOL)flag;

4、不要使用分詞將動詞轉換為形容詞

- (void)setAcceptsGlyphInfo:(BOOL)flag;     ?
- (BOOL)acceptsGlyphInfo;                   ?
- (void)setGlyphInfoAccepted:(BOOL)flag;    ?
- (BOOL)glyphInfoAccepted;                  ?

5表窘、可以使用情態(tài)動詞(can, should, will等)來提高清晰性,但不要使用dodoes

- (void)setCanHide:(BOOL)flag;              ?
- (BOOL)canHide;                            ?
- (void)setShouldCloseDocument:(BOOL)flag;  ?
- (BOOL)shouldCloseDocument;                ?
- (void)setDoesAcceptGlyphInfo:(BOOL)flag;  ?
- (BOOL)doesAcceptGlyphInfo;                ?

6典予、只有在方法需要間接返回多個值的情況下才使用 get

- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;
Delegate方法命名

1、用于通知委托對象操作即將發(fā)生或已經發(fā)生的方法名中要使用 didwill

- (BOOL)browserDidScroll:(NSBrowser *)sender;
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;

2蚊丐、用于詢問委托對象可否執(zhí)行某操作的方法名中可使用didwill但最好使用 should

- (BOOL)windowShouldClose:(id)sender;
集合對象方法命名(Array熙参、Set、Dictionary麦备、Table等)

集合對象(集合中的對象被稱之為元素)約定要具備如下形式的方法

- (void)addElement:(elementType)anObj;
- (void)removeElement:(elementType)anObj;
- (NSArray *)elements;
例如:
- (void)addLayoutManager:(NSLayoutManager *)obj;
- (void)removeLayoutManager:(NSLayoutManager *)obj;
- (NSArray *)layoutManagers;
- (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index;
- (void)removeLayoutManagerAtIndex:(int)index;
方法參數命名

1孽椰、參數采用小駝峰命名
2、不要在參數名中使用 pointerptr凛篙,讓參數的類型來說明它是指針
3吁峻、避免使用 one, two,...,作為參數名
4、避免為節(jié)省幾個字符而縮寫

按照 Cocoa 慣例怔接,以下關鍵字與參數聯(lián)合使用

...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString

xcassets

1犬辰、按模塊分目錄,目錄首字母大寫填物,大駝峰命名

|--CreateOrder
|--DispatchOrder
|--OrderDetail 

2纹腌、圖片命名格式:模塊名稱__ 頁面名稱 __ 控件名稱[__狀態(tài)名稱]

|--CreateOrder
|  |--createOrder_selectAddress_okButton_normal
|  |--createOrder_selectAddress_okButton_highlighted
|  |--createOrder_selectAddress_okButton_disabled
|  |--createOrder_selectAddress_okButton_selected
|  |--createOrder_selectAddress_okButton_focused

strings

1霎终、按模塊分組

// 下單模塊
...
...
 
// 派單模塊
...

2、文案鍵值對升薯,鍵全大寫莱褒,格式:模塊名稱__ 頁面名稱 __ 控件名稱[__狀態(tài)名稱]

// 下單模塊
"CREATEORDER_SELECTADDRESS_OKBUTTON_NORMAL" = "完成";
"CREATEORDER_SELECTADDRESS_CANCELBUTTON_NORMAL" = "取消";
 
// 派單模塊
"DISPATCHORDER_ORDERCARD_RECREATEBUTTON_NORMAL" = "重新下單";
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者涎劈。
  • 序言:七十年代末广凸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蛛枚,更是在濱河造成了極大的恐慌谅海,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹦浦,死亡現(xiàn)場離奇詭異扭吁,居然都是意外死亡,警方通過查閱死者的電腦和手機白筹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門智末,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人徒河,你說我怎么就攤上這事系馆。” “怎么了顽照?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵由蘑,是天一觀的道長。 經常有香客問我代兵,道長尼酿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任植影,我火速辦了婚禮裳擎,結果婚禮上,老公的妹妹穿的比我還像新娘思币。我一直安慰自己鹿响,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布谷饿。 她就那樣靜靜地躺著惶我,像睡著了一般。 火紅的嫁衣襯著肌膚如雪博投。 梳的紋絲不亂的頭發(fā)上绸贡,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼听怕。 笑死捧挺,一個胖子當著我的面吹牛,可吹牛的內容都是我干的尿瞭。 我是一名探鬼主播松忍,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼筷厘!你這毒婦竟也來了?” 一聲冷哼從身側響起宏所,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酥艳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后爬骤,有當地人在樹林里發(fā)現(xiàn)了一具尸體充石,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年霞玄,在試婚紗的時候發(fā)現(xiàn)自己被綠了骤铃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡坷剧,死狀恐怖惰爬,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情惫企,我是刑警寧澤撕瞧,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站狞尔,受9級特大地震影響丛版,放射性物質發(fā)生泄漏。R本人自食惡果不足惜偏序,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一页畦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧研儒,春花似錦豫缨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逸月,卻和暖如春栓撞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工瓤湘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瓢颅,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓弛说,卻偏偏與公主長得像挽懦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子木人,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355