對於屬性:
@property (nonatomic, copy) NSMutableArray *someArray;
若初始化時使用self.someArray:
self.someArray = [[NSMutableArray alloc] initWithCapacity:200];
當使用:
[self.someArray addObject:name];
APP Crash,其中關鍵 Error Info如下:
-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x7f9c89701c20
原因是,通過copy修飾的property,若通過self.someArray =
來賦值初始化,則是通過系統合成setter方法實現,由於設置copy修飾詞,則返回實際上是不可變數組(NSArray),當調用addObject 方法會報錯。
初始化
或者 賦值
部分,做如下修改:
_someArray = [[NSMutableArray alloc] initWithCapacity:200];
則APP運行正常,原因是:_someArray是實例變量,實例變量並沒有 copy 修飾,指向的仍是定義的 NSMutableArray 類型。所以即使後面通過 self.someArray 使用 addObject 方法仍然可行,因為初始化賦值階段獲取的是NSMutableArray類型對象
知道最佳解決方案麼? 其實,就是把
copy
修飾詞改為strong
,因為可變數組對象是個容器,只要其元素中沒有和self對象存在相互持有造成內存洩漏的,則不會出現任何問題。
在之前的文章 Objective-C 2.0 基礎要點歸納 中,對屬性(property)進行了分析,但沒有對關鍵字 @property 和 @synthesize 以及@dynamic的作用進行對比解析,這部分將對之進行詳細分析,但問題卻是因 atomic 修飾詞引出。
關鍵字的作用說明
atomic 是操作原子性,作為屬性修飾詞,則編譯器生產的 getter/setter方法中存在 @synchronized(self)或者lock鎖機制只允許原子性訪問。
若只自定義一個屬性訪問器(setter/getter中一個),會出現warning:writable atomic property ‘name’ cannot pair a synthesized getter with …
若兩個都定義,則需要 @synthesize name = _name; 兩個都自定義的情況下,系統不會合成屬性訪問器,則此時需要顯示調用 @synthesize來定義屬性的實例變量名,以便使用屬性的實例變量
實踐代碼:
TestAtomic 類
TestAtomic.h
#import
@interface TestAtomic : NSObject
@property (atomic, copy) NSString *name;
@end
TestAutomic.m
#import TestAtomic.h
@implementation TestAtomic
@synthesize name = _name;
- (NSString *)name
{
if (![_name isEqualToString:@]) {
return _name;
}
else {
return nil;
}
}
- (void)setName:(NSString *)name
{
@synchronized(self) {
if (![_name isEqualToString:name]) {
_name = name;
}
}
}
@end
TestB 類,繼承TestAtomic類
TestB.h
#import TestAtomic.h
@interface TestB : TestAtomic
@property (atomic, copy) NSString *Bname;
- (instancetype)initWithSuperName;
- (void)print;
@end
TestB.m
#import TestB.h
@implementation TestB
- (instancetype)initWithSuperName
{
self = [super init];
if (self) {
[self setName:@this is A];
}
return self;
}
- (void)print
{
NSLog(@%@ --- %@, self.Bname, self.name);
}
@end
Main 函數:
#import
#include TestAtomic.h
#include TestB.h
int main(int argc, const char * argv[])
{
@autoreleasepool {
TestB *testB = [TestB new];
testB.name = @this is good;
//testB = [testB initWithSuperName];
testB.Bname = @this is B;
[testB print];
}
return 0;
}
NSMutableArray問題
error: writable atomic property cannot pair a synthesized setter/getter
iphone 開發中屬性 property 和 synthesize 權威的介紹
iOS中atomic的實現解析
@synthesize和@dynamic區別