經常使用的屬性修飾符有前端
atomic,nonatomic,strong,retain,weak,assign,unsafe_unretained,copy,readonly,readwritegit
copy
和strong
可變對象 copy是深拷貝程序員
不可變對象 copy是淺拷貝github
mutableCopy 始終是深拷貝數組
copy
修飾NSString/NSArray/NSDictory
由於使用copy來修飾不可變對象,能夠保證安全安全
擴展:async
copy
淺拷貝 不拷貝對象自己,僅僅是拷貝指向對象的指針(複製的對象和原對象都指向同一個地址)函數
mutableCopy
深拷貝 直接拷貝整個對象內存到另外一塊內存中ui
copy
去修飾NSMutableArray
會怎麼樣?使用copy
修飾可變數組以後,數組初始化的時候,會執行copy
方法,生成的是一個不可變的數組,當執行[arr addObject:]
時會crash
atom
atomic
原子性,不是絕對線性安全的
@property (atomic, assign) NSInteger intA; //有一個atomic的屬性,表示是原子的 - (void)viewDidLoad { [super viewDidLoad]; //開啓一個線程對intA的值+1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ for (int i = 0;i < 1000;i ++){ self.intA = self.intA + 1; } NSLog(@"intA : %ld",(long)self.intA); }); //開啓一個線程對intA的值+1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ for (int i = 0;i < 1000;i ++){ self.intA = self.intA + 1; } NSLog(@"intA : %ld",(long)self.intA); }); }
錯誤分析:
由於intA
是atomic
修飾的,因此是線程安全的,在+1
的時候,只會有一個線程去操做,因此最終的打印結果一定有一個是2000
輸出以下:
intA : 1186 intA : 896
分析:
其實atomic
是原子的是沒問題的,這個只是表示set
方法是原子的,效果相似與下面的效果
//atomic表示的是對set方法加鎖,表示在設置值的時候,只會有一個線程執行set方法 - (void)setIntA:(NSInteger)intA{ [self.lock lock]; _intA = intA; [self.lock unlock]; }
只是對set
方法加鎖,而咱們代碼裏面的self.intA = self.intA + 1;
,這一部分不是線程安全的,正確的處理方法是:
[self.lock lock]; self.intA = self.intA + 1; [self.lock unlock];
一個程序至少有一個進程,一個進程至少有一個線程。同一個進程內的線程共享進程裏的資源。
堆 由程序員分配釋放,通常用來存放對象(ARC下會自動釋放)
棧 由編譯器自動分配釋放,存放函數的參數值、局部變量的值等
UIButton
繼承自什麼?爲何?UIButton
是一個能夠響應事件的控件,所以它的直接父類是UIControl
,UIControl
的直接父類是UIView
。
UIButton
從父類UIControl
那繼承了控制相關的方法,好比添加事件、移除事件等
UIResponder
響應者對象,只要繼承自UIResponder
的類,才能處理事件。
UIApplication
、UIView
、UIViewController
都是繼承自UIResponder
類,能夠響應和處理事件。CALayer
不是UIResponder
的子類,沒法處理事件。
事件的分發與傳遞:
1. alpha <0.01 2. userInteractionEnabled = NO 3. hidden = YES.
響應者鏈:
響應鏈是從最合適的view開始傳遞,處理事件傳遞給下一個響應者,響應者鏈的傳遞方法是事件傳遞的反方法,若是全部響應者都不處理事件,則事件被丟棄。咱們一般用響應者鏈來獲取上幾級響應者,方法是UIResponder
的nextResponder
方法。
NSString *str1 = [NSString stringWithFormat:@"hello"]; NSString *str2 = @"hello"; NSString *str3 = @"hello"; if (str1 == str2) { NSLog(@"str1 = str2"); } if (str2 == str3) { NSLog(@"str2 = str3"); } if ([str1 isEqualToString:str2]) { NSLog(@"str1 isEqualToString:str2"); }
輸出以下:
str2 = str3 str1 isEqualToString:str2
這裏考察的是常量池相關的知識點
isEqualToString
比較的是兩個字符串的內容;
而==
比較的是地址的引用;
這裏str2 == str3
返回true
,主要是與常量池有關;在給str2賦值的時候,將hello一塊兒放入了常量池中,當再次將hello賦值給str3的時候,先從常量池中查看是否存在hello的值,若是有,則直接取出。因此str2和str3指的是同一個引用,所以返回的結果天然是true
擴展: iOS程序中的內存分爲:堆區、棧區、全局區(靜態區)、常量區、方法區