OC--@property相關、copy相關

@property相關

一、@property的本質是什么?ivar、getter、setter 是如何生成并添加到這個類中的?

(1)@property=實例變量(ivar)+存取方法(getter和setter);
(2)自動合成(autosynthesis)

二、@protocol協議和category類別中是如何使用@property

(1)只會生成setter和getter方法聲明;
(2)protocol中是希望遵守我協議的對象能實現該屬性;
(3)category需要使用關聯對象:objc_setAssociatedObject和objc_getAssociatedObject

三、@property中有哪些屬性關鍵字?

(1)原子性:nonatomic則不使用自旋鎖,默認是atomic由編譯器合成的方法會通過鎖定機制確保其原子性。
(atomic不是絕對的線程安全,其實無論是否是原子性的只是針對于getter和setter而言,下面有代碼例子)
(2)讀/寫權限:readwrite(讀寫)、readonly(只讀)
(3)內存管理屬性:assign、strong、weak、copy
(4)方法名:getter=<name> 、setter=<name>
例如@property (nonatomic, getter=isOn) BOOL on; BOOL一般命名為isXXX;
setter=<name>一般用在特殊的情境下 new、init開頭屬性,要重新命名。
另外也可以用關鍵字進行特殊說明,來避免編譯器報錯:

@property(nonatomic, readwrite, copy, null_resettable) NSString *initBy;
- (NSString *)initBy __attribute__((objc_method_family(none)));

(5)不常用的:nonnull(不能為空)、nullable(可以為空)、null_resettable(setter可為空, gette不可為空)

一、nonnull 表示不能為空
@property (nonnull, nonatomic, copy) NSString *name;//寫法一
@property (nonatomic, copy) NSString *__nonnull name;//寫法二,小寫時為兩個下劃線
@property (nonatomic, strong) NSString *_Nonnull name;//寫法三,大寫時為一個下劃線
- (void)test{
    
    self.name = nil;//系統會有警告不能給這個屬性賦nil
    
    // 這樣子不提示
    NSString *string = nil;
    self.name = string;//這里系統不會識別到
}

二、nullable 表示可以為空
@property (nullable, nonatomic, copy) NSString *name;//寫法一
@property (nonatomic, copy) NSString *__nullable name;//寫法二,小寫時為兩個下劃線
@property (nonatomic, strong) NSString *_Nullable name;//寫法三,大寫時為一個下劃線

三、null_resettable setter可為空, gette不可為空
setter方法是nullable(可以賦空值),getter方法是nonnull(取值不能為空)
當看到由null_resettable修飾的屬性時,就應該猜想這個屬性的初始化采用了懶加載方式
驗證atomic不是絕對的線程安全
@interface ViewController ()
@property (atomic , strong) NSString *info;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //A
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (1) {
            self.info = @"a";
            NSLog(@"A--info:%@", self.info);
        }
    });

    //B
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (1) {
            self.info = @"b";
            NSLog(@"B--info:%@", self.info);
        }
    });    
    // 根據線程安全定義,如果atomic為線程安全A輸出應該永遠為A--info:a,B輸出應該永遠為B--info:b
    // NSlog會有:A--info:b
}
@end

四、@syncthesize和@dynamic分別有什么作用?

(1)都是@property對應的詞,默認是@syncthesize var=_var;
(2)@syncthesize:編譯器自動實現getter、setter方法;
(3)@dynamic是告訴編譯器,getter、setter方法由用戶自己實現,不自動生成。

@synthesize 合成實例變量(隱藏創建一個_xxx)的規則,有以下幾點:

(1)如果指定了成員變量的名稱,會生成一個指定的名稱的成員變量,
(2)如果這個成員已經存在了就不再生成了.
(3)如果是 @synthesize foo; 會生成一個名稱為foo的成員變量.
(4)默認是@syncthesize var=_var;

默認不寫@syncthesize,是自動合成,如果不寫@syncthesize,一下幾種情況也不自動合成實例變量(隱藏創建一個_xxx)

(1)同時重寫了 setter 和 getter 時
(2)重寫了只讀屬性的 getter 時
(3)使用了 @dynamic 時
(4)在 @protocol 中定義的所有屬性
(5)在 category 中定義的所有屬性
(6)重載的屬性

五、ARC下,默認的屬性修飾是什么?

(1)基本數據類型的是:atomic,readwrite,assign
(2)OC對象的是:atomic,readwrite,strong

六.什么情況使用weak關鍵字?與assign有什么不同?

(1)在ARC中,可能出現循環引用的時候,需要一段設置weak來解決,比如:delegate屬性的修飾。
(2)不同點:weak修飾屬性,弱引用,不會保留新值,也不會釋放舊值,如果舊值被摧毀這個屬性賦值nil,繼續使用不會閃退App。

assign 可以用非 OC 對象( CGFloat 或 NSlnteger 等),而 weak 必須用于 OC 對象,原因是assign修飾的對象被釋放后,指針的地址依然存在,造成野指針,在堆上容易造成崩潰。而棧上的內存系統會自動處理,不會造成野指針。

strong、assign、weak、copy等關鍵相關

七、copy相關

1、怎么用copy關鍵字?

(1)NSString、NSArray、NSDictionry等經常使用copy,因為他們有可變的,如果修飾strong把可變的賦值他們,他們會變成可變,為確保不會無意變動應該使用copy修飾;
(2)Block在ARC下 賦值就是copy,棧復制到堆上;
(3)copy出來的東西是不可變的,mutableCopy出來的東西是可變的

源對象類型 拷貝方法 副本對象類型 是否產生新對象 拷貝類型
NS* copy NS* 淺拷貝
NS* mutableCopy NSMutable* 深拷貝
NSMutable* copy NS* 深拷貝
NSMutable* mutableCopy NSMutable* 深拷貝

注:淺拷貝 == 指針拷貝;深拷貝 == 內容拷貝,深復制需要實現NSCoding協議,實現- (void)copyWithZone:(NSZone *)zone方法

2、父類實現深拷貝時,子類如何實現深度拷貝?

(1)Person的copyWithZone里調用Person *p = [[[self class] alloc] init];
(2)Son的copyWithZone里調用Son *s = [super copyWithZone:zone];
(3)配置Son的屬性

@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
  Person *p = [[[self class] alloc] init]; 
  p. personId = self.personId;
  return p;
}
@end

@implementation Son
- (id)copyWithZone:(NSZone *)zone
{
  Son *s = [super copyWithZone:zone];
  s.studentId = self.studentId;
  return s;
}
@end

3、父類沒有實現深拷貝時,子類如何實現深度拷貝?

(1)Son的copyWithZone里調用Son *s = [[[self class] alloc] init];
(2)配置Person屬性、配置Son的屬性

@implementation Son
- (id)copyWithZone:(NSZone *)zone
{
  Son *s = [[[self class] alloc] init]; 
  s.personId = self. personId;
  s.studentId = self.studentId;
  return s;
}
@end

4、這個寫法會出什么問題: @property (copy) NSMutableArray *array;?
(1)copy出來的對象是不可變的,這個array如果操作add、rem、ins,會崩潰;
(2)使用atomic(默認)原子性線程鎖會影響性能。 nonatomic沒有線程鎖。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 或許是昨天傷心過度了,今天一整天都比較麻木,沒有絲毫的氣力。除了必須打起精神要做的事情之外,整個下午都窩在...
    尋一束光閱讀 217評論 0 0
  • 此前我有很喜歡一個公眾平臺 昨天它發布了一篇文章,講述了一名人民教師,如何在鎂光燈下,摧殘著學生的故事 其中有一個...
    白天很餓閱讀 753評論 2 1
  • 兩個月的放假休息,我 自己也從剛開始的趕點趕卯變成了一堆爛泥巴 。沒有了 緊迫感 ,也不知道自己要干什么了。在他們...
    麥花魔法花園閱讀 237評論 0 0
  • 2017-05-27 檢查出有心肌肥大估計有一個禮拜了,我哭過也崩潰過,更怨更恨 醫生說要限制活動,可是它正是活潑...
    龍微微閱讀 127評論 0 0