設計模式是一種編碼經驗,就是用比較成熟的邏輯去處理某一種類型的事情。設計模式
MVC 和 MVVM 的區別數組
在MVC下,Controller基本是沒法測試的,裏面混雜了個各類邏輯,並且分散在不一樣的地方。有了MVVM咱們就能夠測試裏面的viewModel,來驗證咱們的處理結果對不對(Xcode7的測試已經愈來愈完善了)。安全
好比iOS裏面有iPhone版本和iPad版本,除了交互展現不同外,業務邏輯的model是一致的。這樣,咱們就能夠以很小的代價去開發另外一個app。bash
MVVM是MVC的一個升級版,目前的MVC也能夠很快的轉換到MVVM這個模式。VC能夠省去一大部分展現邏輯。微信
缺點:網絡
每一個VC都附帶一個viewModel,類的數量*2多線程
咱們把邏輯給了viewModel,那勢必Model也會變得很複雜,裏面的屬性和方法愈來愈多。可能重寫的方法比較多,由於涉及到一些數據的轉換以及和controller之間的通訊。app
因爲數據都是從viewModel來,想一想忽然來了一個新人,一看代碼,不知道真實的模型是誰。好比經常使用tableview的數據源,通常都是一個數組,若是不斷的經過viewModel去取,溝通上沒有那麼直接。何況每封一層,意味着要寫不少代碼去融合他們的轉換。oop
Model負責存儲、定義、操做數據;性能
View用來展現給用戶,而且和用戶進行交互;
Controller是Model和View的協調者,Controller把Model中的數據拿過來給View使用。Controller能夠直接與Model和View進行通訊,而View不能與Controller直接通訊。,當有數據更新時,Model也要與Controller進行通訊,這個時候就要用Notification和KVO,這個方式就像發廣播同樣,Model發信號,Controller設置接收監聽信號,當有數據更新是就發信號給Controller,Model和View不能直接通訊,這樣違背MVC設計原則。View與Controller通訊須要利用代理協議的方式,Controller能夠直接根據Model決定View的展現。View若是接受響應事件則經過delegate,target-action,block等方式告訴Controller的狀態變化。Controller進行業務的處理,而後再控制View的展現。
關於MVVM的優勢:
方便測試
便於代碼的移植
兼容MVC
類會增多
viewModel會愈來愈龐大
調用複雜度增長
(1)#import指令是Object-C針對@include的改進版本,能確保引用的文件只會被引用一次,不會陷入遞歸包含的問題中;
(2)@import與@class的區別:
#import會鏈入該頭文件的所有信息,包括實體變量和方法等;二@class只是告訴編譯器,其後面聲明的名稱是類的名稱,至於這些類如何定義的,暫時不用考慮。在頭文件中,通常只須要知道被引用的類的名稱就能夠了,不須要知道其內部的實體變量和方法,因此在頭文件中通常使用@class來聲明這個名稱是類的名稱;而在實現類裏面,由於會用到這個引用類的內部的實體變量和方法,因此須要使用#import類包含這個被引用類的頭文件。
@class還能夠解決循環包含的問題
(3)#import<>跟#import""的區別:
#import<>用來包含系統自帶的文件,#import""用來包含自定義的文件
(4)屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什麼做用,在那種狀況下用?
frame指的是:該view在父view座標系統中的位置和大小。(參照點是父view的座標系統)
bounds指的是:該view在自己座標系統中的位置和大小。(參照點是自己座標系統)
答:Objective-C的類不能夠多重繼承;能夠實現多個接口(協議);Category是類別;通常狀況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其餘類與原有類的關係。
@property 的本質是什麼?
@property = ivar + getter + setter;「屬性」
(property)有兩大概念:ivar(實例變量)、getter+setter(存取方法)
「屬性」 (property)做爲 Objective-C 的一項特性,主要的做用就在於封裝對象中的數據。 Objective-C 對象一般會把其所須要的數據保存爲各類實例變量。實例變量通常經過「存取方法」(access method)來訪問。其中,「獲取方法」 (getter)用於讀取變量值,而「設置方法」 (setter)用於寫入變量值。
屬性能夠擁有的特質分爲四類:
答:
IBOutlet連出來的視圖屬性爲何能夠被設置成weak?
由於父控件的subViews數組已經對它有一個強引用。
不一樣點:
assign 能夠用非 OC 對象,而 weak 必須用於 OC 對象。
weak 代表該屬性定義了一種「非擁有關係」。在屬性所指的對象銷燬時,屬性值會自動清空(nil)。
用途:
NSString、NSArray、NSDictionary 等等常用copy關鍵字,是由於他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary;
block 也常用 copy 關鍵字。
說明:
block 使用 copy 是從 MRC 遺留下來的「傳統」,在 MRC 中,方法內部的 block 是在棧區的,使用 copy 能夠把它放到堆區.在 ARC 中寫不寫都行:對於 block 使用 copy 仍是 strong 效果是同樣的,但寫上 copy 也無傷大雅,還能時刻提醒咱們:編譯器自動對 block 進行了 copy 操做。若是不寫 copy ,該類的調用者有可能會忘記或者根本不知道「編譯器會自動對 block 進行了 copy 操做」,他們有可能會在調用以前自行拷貝屬性值。這種操做多餘而低效。
答:用 @property 聲明 NSString、NSArray、NSDictionary 常用 copy 關鍵字,是由於他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary,他們之間可能進行賦值操做(就是把可變的賦值給不可變的),爲確保對象中的字符串值不會無心間變更,應該在設置新屬性值時拷貝一份。
//總結:使用copy的目的是,防止把可變類型的對象賦值給不可變類型的對象時,可變類型對象的值發送變化會無心間篡改不可變類型對象原來的值。
答:
淺拷貝:只複製指向對象的指針,而不復制引用對象自己。
深拷貝:複製引用對象自己。內存中存在了兩份獨立對象自己,當修改A時,A_copy不變。
問題:添加,刪除,修改數組內的元素的時候,程序會由於找不到對應的方法而崩潰。
緣由:是由於 copy 就是複製一個不可變 NSArray 的對象,不能對 NSArray 對象進行添加/修改。
若想令本身所寫的對象具備拷貝功能,則需實現 NSCopying 協議。若是自定義的對象分爲可變版本與不可變版本,那麼就要同時實現 NSCopying 與 NSMutableCopying 協議。
具體步驟:
需聲明該類聽從 NSCopying 協議
實現 NSCopying 協議的方法。
@property有兩個對應的詞,一個是@synthesize(合成實例變量),一個是@dynamic。
若是@synthesize和@dynamic都沒有寫,那麼默認的就是 @synthesize var = _var;
// 在類的實現代碼裏經過 @synthesize 語法能夠來指定實例變量的名字。(@synthesize var = _newVar;)
@synthesize 的語義是若是你沒有手動實現setter方法和getter方法,那麼編譯器會自動爲你加上這兩個方法。
@dynamic 告訴編譯器,屬性的setter與getter方法由用戶本身實現,不自動生成(如,@dynamic var)。
答:
Objective-C的數據類型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,這些都是class,建立後即是對象,而C語言的基本數據類型int,只是必定字節的內存空間,用於存放數值;NSInteger是基本數據類型,並非NSNumber的子類,固然也不是NSObject的子類。NSInteger是基本數據類型Int或者Long的別名(NSInteger的定義typedef long NSInteger),它的區別在於,NSInteger會根據系統是32位仍是64位來決定是自己是int仍是long。
答:id 聲明的對象具備運行時的特性,便可以指向任意類型的Objcetive-C的對象。
答:Objective-C的內存管理主要有三種方式ARC(自動內存計數)、手動內存計數、內存池。
答:線程建立有三種方法:使用NSThread建立、使用GCD的dispatch、使用子類化的NSOperation,而後將其加入NSOperationQueue;在主線程執行代碼,方法是performSelectorOnMainThread,若是想延時執行代碼能夠用performSelector:onThread:withObject:waitUntilDone:
區別:
分類有名字,類擴展沒有分類名字,是一種特殊的分類。
分類只能擴展方法(屬性僅僅是聲明,並沒真正實現),類擴展能夠擴展屬性、成員變量和方法。
繼承能夠增長,修改或者刪除方法,而且能夠增長屬性。
答:主要是將數據類型的肯定由編譯時,推遲到了運行時。簡單來講, 運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。
答:是爲了防止delegate兩端產生沒必要要的循環引用。
@property (nonatomic, weak) id delegate;
Delegate(委託模式):1對1的反向消息通知功能。
Notification(通知模式):只想要把消息發送出去,告知某些狀態的變化。可是並不關心誰想要知道這個。
KVC(Key-Value-Coding):鍵值編碼 是一種經過字符串間接訪問對象的方式(即給屬性賦值)
舉例說明:
stu.name = @"張三" // 點語法給屬性賦值
[stu setValue:@"張三" forKey:@"name"]; // 經過字符串使用KVC方式給屬性賦值
stu1.nameLabel.text = @"張三";
[stu1 setValue:@"張三" forKey:@"nameLabel.text"]; // 跨層賦值
複製代碼
KVO(key-Value-Observing):鍵值觀察機制 他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
KVO只能被KVC觸發,包括使用setValue:forKey:方法和點語法。
// 經過下方方法爲屬性添加KVO觀察
- (void)addObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(nullable void *)context;
// 當被觀察的屬性發送變化時,會自動觸發下方方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context{}
複製代碼
KVC 和 KVO 的 keyPath 能夠是屬性、實例變量、成員變量。
當一個對象調用setValue方法時,方法內部會作如下操做:
這些方法的默認實現都是拋出異常,咱們能夠根據須要重寫它們。
按照執行順序排列:
class反射
經過類名的字符串形式實例化對象。
Class class = NSClassFromString(@"student");
Student *stu = [[class alloc] init];
複製代碼
將類名變爲字符串。
Class class =[Student class];
NSString *className = NSStringFromClass(class);
複製代碼
SEL的反射
經過方法的字符串形式實例化方法。
SEL selector = NSSelectorFromString(@"setName");
[stu performSelector:selector withObject:@"Mike"];
複製代碼
將方法變成字符串。
NSStringFromSelector(@selector*(setName:));
複製代碼
今天的分享就到這裏了,未完待續
小編這呢,給你們推薦一個優秀的iOS交流平臺,平臺裏的夥伴們都是很是優秀的iOS開發人員,咱們專一於技術的分享與技巧的交流,你們能夠在平臺上討論技術,交流學習。歡迎你們的加入(想要加入的可加小編微信15673450590)。