程序员

Property

2018-06-04  本文已影响0人  墨_辰

干了这么久,我一直觉得自己是个半路出家的IOS开发,虽然是我是正儿八经的科班出生(计算机学院/网络工程专业),但是自己是真的没有接触过ios开发在工作以前,在工作被调来调去以后最终稳定在了IOS开发,然后自己摸爬滚打的开始搞IOS,一边自学一边改项目中的BUG,现在也快要有一年了,感觉自己变成了一个画界面的熟练工,整天在重复的进行一些低复杂度的工作,自己也越来越费,没有一点竞争力。现在我决定开始重新学习Object-C基础。按照《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》这本书的内容重新梳理。希望可以让自己有所成长。

属性介绍:

Objective-C的属性是使用@property语法来声明的公有或私有方法。

@property (readonly, getter=isBlue) BOOL blue;

属性捕获对象的状态。 它们反映了对象的固有属性以及与其他对象的关系。 属性提供了一种安全,便捷的方式来与这些属性进行交互,而不必要手动去编写一组访问方法(如果需要的话,属性也是允许自定义getter和setter方法的)。

我们应当尽可能的使用属性,而不是实例变量。这样有许多的好处:

  1. 自动合成的getter方法和setter方法。 当我们声明了一个属性,编译器会为我们创建默认的gette方法r和setter方法。
  2. 更好地声明一组方法。 由于访问方法的命名约定,可以清楚地知道getter和setter的用处。
  3. 属性的关键词能够传递出相关行为的额外信息。属性提供了一些可能会使用的特质来进行声明,包括assign(vscopy),weak,strong,atomic(vsnonatomic),readwrite,readonly等。

属性方法遵循一个简单的命名约定。 getter方法的名称是属性的名称(属性为date,getter方法也是data),setter方法的名称是set+属性名称,用驼峰命名法编写(setDate)。 BOOL属性的命名约定是用一个以单词“is”开头的命名getter声明它们:

@property (readonly, getter=isBlue) BOOL blue;

如果按照上述的方式声明了属性,那么下面的写法都是可行的:

if (color.blue) { }

if (color.isBlue) { }

if ([color isBlue]) { }

在决定将某些东西声明为属性时,请记住以下几点不可以声明为属性:

init方法;

copy方法,mutableCopy方法;

类工厂方法;

开启某项操作并返回一个BOOL结果的方法;

明确的改变了一个getter的内部状态的副作用方法;

此外,当我们要在自己的代码中使用属性特质时,需要考虑以下的一些规则:

*幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的方法。

如何使用:

确定一组可以被转换为属性的方法,例如:

- (NSColor *)backgroundColor;

- (void)setBackgroundColor:(NSColor *)color;

然后使用对应关键字的@property语法来声明它们:

@property (copy) NSColor *backgroundColor;

有关属性关键字和其他注意事项的信息,请参考Encapsulating Data

或者,您可以使用Xcode中的现代Objective-C转换器自动对您的代码进行更改。 有关更多信息,请参考Refactoring Your Code Using Xcode

以上内容翻译自Adopting Modern Objective-C

举个例子吧,我的理解

@property(nonatomic, copy) NSString* folderName;

下面两个调用方式是一样的(前面是getter方法和setter方法,后面是等价的点方法)

[self setFolderName:@"XiaoMing"] <=> self.folderName = @"XiaoMing";

[self folderName] <=> self.folderName;

setter方法和getter方法实现如下:

//setter方法

- (void)setFolderName:(NSString *)folderName {

 _folderName = folderName;

}

//getter方法

- (NSString*)folderName {

 return _folderName;

}

其实在整个属性里面最重要的还是属性特质,下面分为几组进行学习:

1.atomic/nonatomic(默认为atomic)

指定合成存取方法是否为原子操作,可以理解为是否线程安全,但在iOS上并不要求属性必须是原子的(atomic),因为这并不能保证线程安全,要保证线程安全需要使用更深层次的锁机制才行。

几乎所有IOS代码的属性设置都会使用nonatomic,这样做的原因是,在iOS中使用同步锁的开销较大,会带来性能问题。

2.readwrite/readonly(默认为readwrite

readwrite表示自动生成getter方法和setter方法,不需要自己定义。readonly表示只合成getter方法而不合成setter方法。

3.assignweakunsafe_unretained

assign表示对属性只进行简单的赋值操作,不更改所赋的新值的引用计数,也不改变旧值的引用计数,常用于标量类型,如NSInteger,NSUInteger,CGFloat,NSTimeInterval等。也可用于修饰NSString,但是容易引发野指针问题,一般不会用于修饰NSString。

使用weak修饰的时候同样不会增加所赋的新值的引用计数,也不减少旧值的引用计数,但当该值被销毁时,weak修饰的属性会被自动赋值为nil,这样就可以避免野指针错误。

使用unsafe_unretained修饰时效果与assign相同,不会增加引用计数,当所赋的值被销毁时不会被置为nil,可能会发生野指针问题。unsafe_unretained与assign的区别在于,unsafe_unretained只能修饰对象,不能修饰标量类型,而assign两者均可修饰。

4.strongweak

strong表示属性对所赋的值持有强引用表示一种“拥有关系”(owning relationship),会先保留新值即增加新值的引用计数,然后再释放旧值即减少旧值的引用计数。只能修饰对象。如果对一些对象需要保持强引用则使用strong修饰。

weak表示对所赋的值对象持有弱引用表示一种“非拥有关系”(nonowning relationship),对新值不会增加引用计数,也不会减少旧值的引用计数。所赋的值在引用计数为0被销毁后,weak修饰的属性会被自动置为nil,能够有效防止野指针错误。

weak常用在修饰delegate等防止循环引用的场景。

5.copy

copy修饰的属性会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰有对应可变类型子类的对象,比如NSString,NSArray等。为确保这些不可变对象因为可变子类对象影响,需要copy一份备份,如果不使用copy修饰,使用strong或assign等修饰则会因为多态导致属性值被修改。

参考文章:

https://www.jianshu.com/p/646ae400fe7b

更加深入理解的文章:

https://www.jianshu.com/p/44d12884e24e

上一篇下一篇

猜你喜欢

热点阅读