設計模式
1.delegate和notification什么區別,什么情況使用?
2.描述一下KVO和KVC。
Key-Value Observing (簡寫為KVO):當指定的對象的屬性被修改了,允許對象接受到通知的機制。每次指定的被觀察對象的屬性被修改的時候,KVO都會自動的去通知相應的觀察者。
KVC是KeyValue Coding的簡稱,它是一種可以直接通過字符串的名字(key)來訪問類屬性的機制。而不是通過調用Setter、Getter方法訪問。
3簡述NotificationCenter、KVC、KVO、Delegate?并說明它們之間的區別?
答:消息中心,消息通知;
利用鍵-值間接訪問類中的某個屬性
利用鍵-路徑間接訪問類中的某個屬性,也稱觀察者模式
代理,多用于兩個類之間的傳值
15.你熟悉的設計模式有哪些,請說說對他們的理解。
答:單例,通知,KVO,代理,target-action等
單例,主要特點是一個類只有一個對象。對外提供了一個獲取唯一對象的方法,一般都是類方法,完整的單例會重寫很多引用計數相關的方法(比如:allocWithZone,copyWithZone,retain,release,autorelease,retainCount等)以保證對象在任何情況下都唯一。單例最大的價值就是建立程序級別的全局變量,就是把不同模塊都要用的變量以屬性的形式放到單例里面,以便隨時使用。音頻播放類程序一般會寫單例來管理需要播放的音樂信息,需要下載的地方也會以單例的形式來管理下載對象。
通知,是M與C通信的方式之一。一般是Model發送變化的時候,會發送通知告訴Controller,Controller再做相應的處理。需要先往通知中心里面注冊觀察者,然后在合適的時機,通知中心post通知,觀察者做對應的處理,當觀察者將要釋放的時候,從通知中心移除觀察者。
KVO,也是M與C通訊的方式。一般是C去觀察M的某個屬性,某個屬性發生變化之后,C做出相應的處理,當C將要釋放的時候,M移除觀察者。
代理,是V與C通信的方式之一。一般C是V的代理,V發生變化的時候,C做對應的調整。例如:UITableView被點擊了,由Controller做處理。我們在自己寫代理的時候,一定要清楚誰來處理事件,誰來調用代理方法。通常情況下都是C處理時間,V在適當的時候調用代理方法。
target-action,也是V與C通信的方式之一。一般C是V的target,V被點擊或者被滑動之后,C做出對應的處理。無論是target-action還是代理,核心都是回調。
8.在使用系統的一些類例如UITableView時,會發現其delegate屬性的語義設置為assign而不是retain,為什么呢?
答:delegate的語義修飾符 為assign不是retain主要是為了避免兩個對象因相互引用造成的內存泄露問題。
因為retain修飾delegate,當通過set方法賦值時,對象的引用計數會+1.
如果此時兩個對象具有如下關系:A對象有一個屬性是B,B的delegate是A。即互相為彼此的屬性。例如:A是viewController,B是tableView. ?B是A的屬性,B的引用計數會+1,B的delegate是A,A的引用計數也會+1.那么如果A沒有釋放,B就一直不會釋放,因為A對B有擁有權。 同理,B沒有釋放,A也一直釋放不掉,因為B對A也有擁有權。 因此A和B的dealloc都會不執行,造成內存泄露.
代碼演示如下(只寫出了核心代碼):
A *a = ?[[A alloc] init] // a引用計數:1
B *b = ?[[B alloc] init] // b引用計數:1
a.b = b; // b引用計數:2
b.delegate = a; // a引用計數:2
[a release]; // a引用計數:1
[b release]; // b引用計數:1
//最終A和B都釋放不掉。
assign則是直接賦值,并不會引起引用計數增加,因此使用assign不會出現內存泄露。
代碼演示如下(只寫出了核心代碼):
A *a = ?[[A alloc] init] // a引用計數:1
B *b = ?[[B alloc] init] // b引用計數:1
a.b = b; // b引用計數:2
b.delegate = a; // a引用計數:1
[a release]; // a引用計數:0,b引用計數:1(在a的dealloc里面_b被釋放了)
[b release]; // b引用計數:0
//最終A和B都可以釋放掉。
13.NSNotification和KVO的區別和用法是什么?什么時候應該使用通知,什么時候應該使用KVO,它們的實現上有什么區別?
答:通知和KVO都是觀察者模式的體現,二者側重點有些不同。
通知往往用于1對多的場景,多個觀察者觀察一個通知,一旦這個通知被通知中心post,所有觀察者都可以做出響應。具體的實現流程是:(1)通知中心通過addObserver方法添加觀察者,其實是把觀察者和通知進行綁定,多次使用addObserver方法可以為同一個通知添加多個觀察者。(2)通知中心發送通知。(3)各個觀察者做各自的處理。(4)在觀察者銷毀之前(dealloc中),從通知中心移除觀察者。
KVO多用于1對1的場景,一個對象去觀察另外一個對象的屬性值有沒有發生變化,一旦發生變化,觀察者做出響應。具體的流程是:(1)被觀察者添加觀察者,指定觀察者觀察的屬性。(2)被觀察者的屬性在某一時間發生了變化。(3)觀察者做出響應。(4)在觀察者銷毀之前,先移除觀察者。
KVO其實也可以1對多,就是多個觀察者觀察同一個對象同一個屬性的變化。KVO和通知給人的感覺一個主動通知(通知會由通知中心主動post),一個是被動通知(KVO,觀察者一直盯著屬性變沒變,一旦變化,自己就做出響應。被觀察的對象不是主動告知你我變了)。
23.定義一個返回值為字符串類型,參數是int類型的Block。并且調用該Block。
答:Block定義如下所示:
NSString * (^block)(int a) = ^ NSString * (int a){
return [NSString ?stringWithFormat:“%d”,a];
};
Block調用:
NSString *str = block(10);
24.請談談你對block和delegate模式認識?
答:無論是block還是delegate模式本質上都是回調,使用block,其優點是回調的block代碼塊直接就放在了block賦值的地方,使代碼更為緊湊,缺點是block內使用到當前類的實例變量的時候,需要注意循環引用的問題,即需要使用__block(MRC下)或者__weak(ARC下)定義一個弱引用的self出來,block里面使用弱引用的self去操作屬性或調用方法。delegate模式不用像block一樣做特殊處理,但是如果多個對象設置的代理是同一個對象,就需要在delegate方法中判斷當前執行代理的是哪個對象。
1、block的作用?
1.__block對象在block中是可以被修改、重新賦值的;
2.__block對象在block中不會被block強引用一次,從而不會出現循環引用的問題。
2、block里面能不能修改靜態變量(能,__block可以)為什么要用__block
你可以指定引入一個變量為可更改的,即讀-寫的,通過應用__block存儲類型修 飾符。局部變量的__block的存儲和register、auto、static等存儲類型相似,但它們之 間不兼容。
__block變量保存在變量共享的作用域范圍內,所有的blocks和block副本都聲明 或創建在和變量的作用域相同范圍內。所以,如果任何blocks副本聲明在棧內并未超 出棧的結束時,該存儲會讓棧幀免于被破壞(比如封裝為以后執行)。同一作用域范 圍內給定的多個block可以同時使用一個共享變量
作為一種優化,block存儲在棧上面,就像blocks本身一樣。如果使用Block_copy拷貝了block的一個副本(或者在Objective-C里面給block發送了一條copy消息),變量會被拷貝到堆上面。所以一個__block變量的地址可以隨時間推移而被更改。
使用__block的變量有兩個限制:它們不能是可變長的數組,并且它們不能是包 含有C99可變長度的數組變量的數據結構。
3、聲明一個block
聲明block
int (^myblock) (int)
說明:第一個int是block的返回值myblock是block變量 ? ? 第二個int是參數
//舉例
在.h中
typedef void(^MyBlock)(int value);
@property (nonatomic,weak) MyBlock block;
-(void)setMyBlock:(void(^)(int value)) block;
在.m中
-(void)setMyBlock:(void(^)(int value)) block {
if (block) {
self.block=block;
}
}
11、ios使用block應當注意什么?
(1)block在實現時就會對它引用到的它所在方法中定義的棧變量進行一次只讀拷貝,然后在block塊內使用該只讀拷貝。
(2)非內聯(inline)block不能直接訪問self,只能通過將self當作參數傳遞到block中才能使用,并且此時的self只能通過setter或getter方法訪問其屬性,不能使用句點式方法。但內聯block不受此限制。
(3)使用weak–strong dance技術來避免循環引用
(4)block內存管理分析
block其實也是一個NSObject對象,并且在大多數情況下,block是分配在棧上面的,只有當block被定義為全局變量或block塊中沒有引用任何automatic變量時,block才分配在全局數據段上。__block變量也是分配在棧上面的。在ARC下,編譯器會自動檢測為我們處理了block的大部分內存管理,但當將block當作方法參數時候,編譯器不會自動檢測,需要我們手動拷貝該block對象。
在ARC下,對block變量進行copy始終是安全的,無論它是在棧上,還是全局數據段,還是已經拷貝到堆上。對棧上的block進行copy是將它拷貝到堆上;對全局數據段中的block進行copy不會有任何作用;對堆上的block進行copy只是增加它的引用記數。
如果棧上的block中引用了__block類型的變量,在將該block拷貝到堆上時也會將__block變量拷貝到堆上如果該__block變量在堆上還沒有對應的拷貝的話,否則就增加堆上對應的拷貝的引用記數。
http://my.oschina.net/u/1432769/blog/390401
2.kvo除了能觀察屬性外,能不能觀察對象
不能觀察對象
KVO,即:Key-Value Observing,它提供一種機制,當指定的對象的屬性被修改后,則對象就會接受到通知。簡單的說就是每次指定的被觀察的對象的屬性被修改后,KVO就會自動通知相應的觀察者了
KVO是一個對象能夠觀察另外一個對象的屬性的值,并且能夠發現值的變化。這是一個對象與另外一個對象保持同步的一種方法,即當另外一種對象的狀態發生改變時,觀察對象馬上作出反應。它只能用來對屬性作出反應,而不會用來對方法或者動作作出反應。
實現原理:當為某一個對象屬性注冊監聽的時候,該對象的isa指針就會指向一個中間類,而不是本來對象真實的類。所以說,對象的isa指針可以改變,我們的程序最好不要依賴isa指針。
簡而言之就是:
1、當一個object有觀察者時,動態創建這個object的類的子類
2、對于每個被觀察的property,重寫其set方法
3、在重寫的set方法中調用- willChangeValueForKey:和- didChangeValueForKey:通知觀察者
4、當一個property沒有觀察者時,刪除重寫的方法
5、當沒有observer觀察任何一個property時,刪除動態創建的子類
10、簡述在app中所應用到設計模式
(一)代理模式
應用場景:當一個類的某些功能需要由別的類來實現,但是又不確定具體會是哪個類實現。
優勢:解耦合
敏捷原則:開放-封閉原則
實例:tableview的 數據源delegate,通過和protocol的配合,完成委托訴求。
列表row個數delegate
自定義的delegate
(二)觀察者模式
應用場景:一般為model層對,controller和view進行的通知方式,不關心誰去接收,只負責發布信息。
優勢:解耦合
敏捷原則:接口隔離原則,開放-封閉原則
實例:Notification通知中心,注冊通知中心,任何位置可以發送消息,注冊觀察者的對象可以接收。
kvo,鍵值對改變通知的觀察者,平時基本沒用過。
(三)MVC模式
應用場景:是一中非常古老的設計模式,通過數據模型,控制器邏輯,視圖展示將應用程序進行邏輯劃分。
優勢:使系統,層次清晰,職責分明,易于維護
敏捷原則:對擴展開放-對修改封閉
實例:model-即數據模型,view-視圖展示,controller進行UI展現和數據交互的邏輯控制。
(四)單例模式
應用場景:確保程序運行期某個類,只有一份實例,用于進行資源共享控制。
優勢:使用簡單,延時求值,易于跨模塊
敏捷原則:單一職責原則
實例:[UIApplication sharedApplication]。
注意事項:確保使用者只能通過getInstance方法才能獲得,單例類的唯一實例。
java,C++中使其沒有公有構造函數,私有化并覆蓋其構造函數。
object c中,重寫allocWithZone方法,保證即使用戶用alloc方法直接創建單例類的實例,
返回的也只是此單例類的唯一靜態變量。
(五)策略模式
應用場景:定義算法族,封裝起來,使他們之間可以相互替換。
優勢:使算法的變化獨立于使用算法的用戶
敏捷原則:接口隔離原則;多用組合,少用繼承;針對接口編程,而非實現。
實例:排序算法,NSArray的sortedArrayUsingSelector;經典的鴨子會叫,會飛案例。
注意事項:1,剝離類中易于變化的行為,通過組合的方式嵌入抽象基類
2,變化的行為抽象基類為,所有可變變化的父類
3,用戶類的最終實例,通過注入行為實例的方式,設定易變行為
防止了繼承行為方式,導致無關行為污染子類。完成了策略封裝和可替換性。
(六)工廠模式
應用場景:工廠方式創建類的實例,多與proxy模式配合,創建可替換代理類。
優勢:易于替換,面向抽象編程,application只與抽象工廠和易變類的共性抽象類發生調用關系。
敏捷原則:DIP依賴倒置原則
實例:項目部署環境中依賴多個不同類型的數據庫時,需要使用工廠配合proxy完成易用性替換
注意事項:項目初期,軟件結構和需求都沒有穩定下來時,不建議使用此模式,因為其劣勢也很明顯,
增 加了代碼的復雜度,增加了調用層次,增加了內存負擔。所以要注意防止模式的濫用。
8.使用block和使用delegate完成委托模式有什么優點?
委托模式在iOS中大量應用,其在設計模式中是適配器模式中的對象適配器,Objective-C中使用id類型指向一切對象,使委托模式更為簡潔。
block
優點:
1.語法簡潔,實現回調不需要顯示的調用方法,代碼更為緊湊。
2.增強代碼的可讀性和可維護性。
3.配合GCD優秀的解決多線程問題。
缺點:
1.Block中得代碼將自動進行一次retain操作,容易造成內存泄露。
2.Block內默認引用為強引用,容易造成循環引用。
代理:
優點:
1.減少代碼的耦合性,使事件監聽和事件處理相分離。
2.清晰的語法定義,減少維護成本,較強的代碼可讀性。
3.不需要創建第三方來監聽事件和傳輸數據。
4.一個控制器可以實現多個代理,滿足自定義開發需求,可選必選有較大的靈活性。
缺點:
1.實現委托的代碼過程比較繁瑣。
2.當實現跨層傳值監聽的時候將加大代碼的耦合性,并且程序的層次結構將變的混亂。
3.當對多個對象同時傳值響應的時候,委托的易用性將
10.何時使用代理,何時使用通知;
代理:一般控件用的比較多,其實也可以用block實現,如果實現的接口比較多的話,建議用代理,如UITableview。
如果一個類能夠獲取到通知的對象,這種情況下,我們用代理的效率會更高,而且能夠更好的實現對要代理的對象的管理。
通知:這東西是全局的,而且是同步的,如果你要全局發送消息,并且做的事情時間不長,不會阻塞線程的話,建議使用。
如果一個通知的發送者有多個接受者,而且接受的位置完全不確定,那么這種情況下用通知是比較好的方式
37. block在ARC中和MRC中的用法有什么區別,需要注意什么
①.對于沒有引用外部變量的Block,無論在ARC還是非ARC下,類型都是__NSGlobalBlock__,這種類型的block可以理解成一種全局的block,不需要考慮作用域問題。同時,對他進行Copy或者Retain操作也是無效的
②.應注意避免循環引用
36.類工廠方法是什么
類工廠方法的實現是為了向客戶提供方便,它們將分配和初始化合在一個步驟中, 返回被創建的對象,并
進行自動釋放處理。這些方法的形式是+ (type)className...(其中className不包括任何前綴)。
工廠方法可能不僅僅為了方便使用。它們不但可以將分配和初始化合在一起,還可以 為初始化過程提供對
象的分配信息。
類工廠方法的另一個目的是使類(比如NSWorkspace)提供單件實例。雖 然init...方法可以確認一
個類在每次程序運行過程只存在一個實例,但它需要首先分配一個“生的”實例,然后還必須釋放該實例。
工廠 方法則可以避免為可能沒有用的對象盲目分配內存。
43.代理和協議什么區別
代理是一種概念,協議是一種技術,代理是用協議來實現的,代理 是2個對象之間通訊的一種方式。 代理主要做反向傳值的。實現系統的一些回調方法,比如scrollview滑動事件,選擇照片,asi網絡下載完成等.iOS開發和Objective-c區別
50.在block內如何修改block外部變量?
默認情況下,在block中訪問的外部變量是復制過去的,即:寫操作不對原變量生效。但是你可以加上__block來讓其寫操作生效,示例代碼如下:
__block int a = 0;
void ?(^foo)(void) = ^{
a = 1;
}
f00();
//這里,a的值被修改為1
53.使用block時什么情況會發生引用循環,如何解決?
一個對象中強引用了block,在block中又使用了該對象,就會發射循環引用。 解決方法是將該對象使用__weak或者__block修飾符修飾之后再在block中使用。
id weak weakSelf = self;或者weak __typeof(&*self)weakSelf = self該方法可以設置宏
id __block weakSelf = self;
block中的weak self,是任何時候都需要加的么?
(2)block
block在copy時都會對block內部用到的對象進行強引用(ARC)或者retainCount增1(非ARC)。在ARC與非ARC環境下對block使用不當都會引起循環引用問題,一般表現為,某個類將block作為自己的屬性變量,然后該類在block的方法體里面又使用了該類本身,簡單說就是self.someBlock = ^(Type var){[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};block的這種循環引用會被編譯器捕捉到并及時提醒
95.哪些類不適合使用單例模式?即使他們在周期中只會出現一次。
工具類,不需要存儲數據的.
簡明概要的說明了KVO和NSNotification的區別:
和delegate一樣,KVO和NSNotification的作用也是類與類之間的通信,與delegate不同的是1)這兩個都是負責發出通知,剩下的事情就不管了,所以沒有返回值;2)delegate只是一對一,而這兩個可以一對多。這兩者也有各自的特點。
1)KVO的使用:
被觀察者發出addObserver:forKeyPath:options:context:方法來添加觀察者。
然后只要被觀察者的keyPath值變化(注意:單純改變其值不會調用此方法,只有通過getters和setters來改變值才會觸發KVO),就會在觀察者里調用方法observeValueForKeyPath:ofObject:change:context:
因此觀察者需要實現方法observeValueForKeyPath:ofObject:change:context:來對KVO發出的通知做出響應。
這 些代碼都只需在觀察者里進行實現,被觀察者不用添加任何代碼,所以誰要監聽誰注冊,然后對響應進行處理即可,使得觀察者與被觀察者完全解耦,運用很靈活很 簡便;但是KVO只能檢測類中的屬性,并且屬性名都是通過NSString來查找,編譯器不會幫你檢錯和補全,純手敲所以比較容易出錯。
2)NSNotification的使用
這里的通知不是由被觀察者發出,而是由NSNotificationCenter來統一發出,而不同通知通過唯一的通知標識名notificationName來區分,標識名由發送通知的類來起。
首先被觀察者自己在必要的方法A里,通過方法postNotificationName:object:來發出通知notificationName這樣發送通知者這邊的工作就完成了,每次A被調用,就會發送一次通知notificationName。
然后誰要監聽A的變化,就通過[NSNotificationCenter defaultCenter]的方法addObserver:selector:name:object:為觀察者注冊監聽name為notificationName的通知然后每次發出name為notificationName的通知時,注冊監聽后的觀察者就會調用其自己定義的方法notificationSelector來進行響應。
NSNotification的特點呢,就是需要被觀察者先主動發出通知,然后觀察者注冊監聽后再來進行響應,比KVO多了發送通知的一步,但是其優點是監聽不局限于屬性的變化,還可以對多種多樣的狀態變化進行監聽,監聽范圍廣,使用也更靈活。
MVC模式及好處?
MVC是三個單詞的縮寫,分別為:
模型(Model),視圖(View)和控制Controller)。
MVC模式的目的就是實現Web系統的職能分工。
Model層實現系統中的業務邏輯,通常可以用JavaBean或EJB來實現。
View層用于與用戶的交互,通常用JSP來實現。
Controller層是Model與View之間溝通的橋梁,它可以分派用戶的請求并選擇恰當的視圖以用于顯示,同時它也可以解釋用戶的輸入并將它們映射為模型層可執行的操作。
MVC模式的好處
1.各施其職,互不干涉
在MVC模式中,三個層各施其職,所以如果一旦哪一層的需求發生了變化,就只需要更改相應的層中的代碼而不會影響到其它層中的代碼。
2.有利于開發中的分工
在MVC模式中,由于按層把系統開,那么就能更好的實現開發中的分工。網頁設計人員可以進行開發視圖層中的JSP,對業務熟悉的開發人員可開發業務層,而其它開發人員可開發控層。
3.有利于組件的重用
分層后更有利于組件的重用。如控制層可獨立成一個能用的組件,視圖層也可做成通用的操作界面。
MVC(Model-View-Controller)應用程序結構被用來分析分布式應用程序的特征。這種抽象結構能有助于將應用程序分割成若干邏輯部件,使程序設計變得更加容易。
MVC結構提供了一種按功能對各種對象進行分割的方法(這些對象是用來維護和表現數的),其目的是為了將各對象間的耦合程度減至最小。MVC結構本來是為了將傳統的輸入(input)、處理(processing)、輸出(output)任務運用到圖形化用戶交互模型中而設計的。但是,將這些概念運用于基于Web的企業級多層應用領域也是很適合的。
在MVC結構中,模型(Model)代表應用程序的數據(data)和用于控制訪問和修改這些數據的業務規則(business rule)。通常模型被用來作為對現實世界中一個處理過程的軟件近似,當定義一個模型時,可以采用一般的簡單的建模技術。
當模型發生改變時,它會通知視(View),并且為視提供查詢模型相關狀態的能力。同時,它也為控制器(Controller)提供訪問封裝在模型內部的應用程序功能的能力。
一個視(View)用來組織模型的內容。它從模型那里獲得數據并指定這些數據如何表現。當模型變化時,視負責維持數據表現的一致性。視同時將用戶要求告知控制器(Controller)。
控制器(Controller)定義了應用程序的行為;它負責對來自視的用戶要求進行解釋,并把這些要求映射成相應的行為,這些行為由模型負責實現。在獨立運行的GUI客戶端,用戶要求可能是一些鼠標單擊或是菜單選擇操作。在一個Web應用程序中,它們的表現形式可能是一些來自客戶端的GET或POST的HTTP請求。模型所實現的行為包括處理業務和修改模型的狀態。根據用戶要求和模型行為的結果,控制器選擇一個視作為對用戶請求的應答。通常一組相關功能集對應一個控制器。
1)各施其職,互不干涉
在MVC模式中,三個層各施其職,所以如果一旦哪一層的需求發生了變化,就只需要更改相應的層中的代碼而不會影響到其它層中的代碼。假如業務發生了變化,如在取文章時可能webmaster把一些文章作了無效標志,不能直接把所有文章取出來,只能取出有效的文章,這時業務就發生了改變。再設想一下,如果這個業務邏輯在100個頁面中都要用到,那么MVC模式就體現了它的靈活性。我們可以不更改任何JSP,只要更改model層中的相應類中的SQL語句即可。
2)有利于開發中的分工
在MVC模式中,由于按層把系統開,那么就能更好的實現開發中的分工。網頁設計人員可以進行開發視圖層中的JSP,對業務熟悉的開發人員可開發業務層,而其它開發人員可開發控制層。
3)有利于組件的重用
分層后更有利于組件的重用。如控制層可獨立成一個能用的組件,視力層也可做成通用的操作界面
10、聲明block屬性的時候為什么?用copy?
避免block被系統釋放,因為?一開始block是在棧中的,只有copy后的block才會
在堆中。
Block屬性的聲明,?首先需要?用copy修飾符,因為只有copy后的Block才會在堆中,棧中的Block的?生命周期是和棧綁定的,避免編譯器將其釋放;
(拓展)block與線程安全另?一個需要注意的問題是關于線程安全,在聲明Block屬性時需要確認“在調?用
Block時另?一個線程有沒有可能去修改Block?”這個問題,如果確定不會有這種情況發?生的話,那么Block屬性聲明可以?用nonatomic。如果不肯定的話(通常情況是這樣的),那么你?首先需要聲明Block屬性為atomic,也就是先保證變量的原?子性(Objective-C并沒有強制規定指針讀寫的原?子性,C#有)。
?比如這樣?一個Block類型: typedef void (^MyBlockType)(int);
屬性聲明:
@property (copy) MyBlockType myBlock;
這?里ARC和?非ARC聲明都是?一樣的,當然注意在?非ARC下要release Block。
但是,有了atomic來保證基本的原?子性還是沒有達到線程安全的,接著在調?用時需要把Block先賦值給本地變量,以防?止Block突然改變。因為如果不這樣的話,即便是先判斷了Block屬性不為空,在調?用之前,?一旦另?一個線程把Block屬性設空了,程序就會crash,如下代碼:
if (self.myBlock)
{
//此時,?走到這?里,self.myBlock可能被另?一個線程改為空,造成crash //注意:atomic只會確保myBlock的原?子性,這種操作本?身還是?非線程安全的self.myBlock(123);
}
所以正確的代碼是(ARC): MyBlockType block = self.myBlock; //block現在是本地不可變的
if (block)
{ block(123); }
在?非ARC下則需要?手動retain?一下,否則如果屬性被置空,本地變量就成了野指針了,如下代碼:
//?非ARC
MyBlockType block = [self.myBlock retain];
if (block)
{ block(123); }
[block release];
4.(口述)NSNotification和KVO的區別和用法是什么?什么時候應該使用通知,什么時候應該使用KVO,它們的實現上有什么區別嗎?如果用protocol和delegate(或者delegate的Array)來實現類似的功能可能嗎?如果可能,會有什么潛在的問題?如果不能,為什么?
2、非自動內存管理情況下怎么做單例模式
非ARC內存管理模式下對象必須手動釋放,為了防止那個唯一的單例對象被釋放掉,則只需要重寫下面的幾個方法即可
+(instancetype) allocWithZone:(struct _NSZone *)zone
-(instancetype) copyWithZone:(NSZone*)zone
-(id) retain
-(oneway void) release
-(instancetype) autorelease
-(unsigned) retainCount
http://www.cnblogs.com/heyonggang/p/3553840.html
4、What is Singleton pattern? Please try to implement one
單例模式的意思就是只有一個實例。單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。這個類稱為單例類。
在iOS中,單例有兩種實現方式。根據線程安全的實現來區分,一種是使用@synchronized,另一種是使用GCD的dispatch_once函數。
要實現單例,首先需要一個static的指向類本身的對象,其次需要一個初始化類函數。下面是兩種實現的代碼。
1、@synchronized
static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
@synchronized (self){
if (instance == nil) {
instance = [[InstanceClass alloc] init];
}
}
return instance;
}
2、GCD
static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[InstanceClass alloc] init];
});
return instance;
}
2.MRC下的單例需要注意什么
因為 單例對象 是用static標記過的,因此存放在 靜態區.所以在MRC中 不需要 由程序員 去管理,因此要去覆蓋一些 內存 管理的方法.
實現部分與ARC一致,只需要 覆蓋 一些MRC中 內存 管理 的方法:
* - ?(id)retain .單例中不需要增加引用計數器. return self.
* - (id)autorelease .只有堆中的對象才需要.單例中不需要.return self.
* - (NSUInteger)retainCount . (可寫可不寫,防止引起誤解).單例中不需要修改引用計數,返回最大的無符號整數即可.return UINT_MAX;
*- (oneway void)release .不需要release.直接覆蓋,聲明也不做.
單例模式(ARC)與(MRC)
http://www.mamicode.com/info-detail-364051.html
i??????