实例变量:
属性其实说直白点就是 ivar + setter + getter(实例变量+存取方法),不过在OC中属性多了字面量这一系列特殊关键字使得OC属性有些不同。

成员属性我们应该都使用过,比如现在定义一个Car类有name和speed成员变量:

#import <Foundation/Foundation.h>

@interface Car : NSObject
{
@public
NSString *name;
NSInteger speed;
}
@end

在OC类的内部有一个偏移量,专门标记成员变量在内存中的所在位置。如果现在在添加一个新的成员变量在name的前面,那么就会出现偏移量整体便宜的问题,现在添加一个price实例:

#import <Foundation/Foundation.h>

@interface Car : NSObject
{
@public
NSInteger price;
NSString *name;
NSInteger speed;
}
@end

此时偏移量在内存中显示如下:

Car Car
name price
speed name
  speed

可以看到实例偏移量发生了改变,但是OC将实例变量作为一种存储偏移量所用的“特殊变量”,交个类对象(class object)保管,偏移量会在运行时查找,所以总能正确的找到偏移量。

@Property

使用属性相比成员变量更加抽象,能够使用setter和getter对变量做更多的处理。

说一下属性的特性

@synthesize关键字

该关键字指定了属性的实例变量名称,并且根据存储语义(readwrite、readonly)系统自动合成setter和getter方法,当然也可以手写来覆盖系统提供的。

@dynamic

该关键字告诉编译器不要为我合成setter和getter方法,这些方法将由我自己实现。当然我们可以不实现这在编译阶段不会出现问题,直到运行时才会检查是否实现了setter和getter,如果没有实现就会抛出异常。

例如在CoreData中NSManagedObject子类的所有属性全部都是dynamic标记的,这是因为子类的某些属性不是真正的实例变量,而是对应背后的数据库,对NSManagedObject对象通过是属性访问时会自动使用KVC。

属性特性(语义)

属性的特质分为四类:

1.原子性:

  原子性就是指该属性是否为同步的,OC中大部分属性都是nonatomic(非原子性)的,如果不写nonatomic那么就会是原子性的。理论上来说原子性属性的读写都将会是同步的,但是OC中atomic并不能一定确定属性为同步的,如果真要进行同步操作,还要用更加深层次的同步锁API。而且atomic会很影响效率,所以一般都会写nonatomic。

2.读/写权限:

  读写为readonly和readwrite两种,前一种在系统只会合成getter方法,而后一种则会同时生成setter和getter。如果属性设置为了readonly属性,那么该属性是不可以修改的。

3.内存管理语义:

  assign:该方法只会针对“纯量类型”(CGFloat或NSInteger等)的简单赋值操作,id类型也要用assign,所以一般iOS中的代理delegate属性都会用assign来标示,如:

@property (nonatomic, assign)   id <UITableViewDataSource> dataSource;
@property (nonatomic, assign) id <UITableViewDelegate> delegate;

  strong: 使用该特性实例变量在赋值时,会释放旧值同时设置新值,对对象产生一个强引用,用MRC来说就是引用计数+1。

  weak: 属性表明了一种”非拥有关系“,既不释放旧值,也不保留新值。用MRC就是引用计数不变,当指向的对象被释放时,该属性自动被设置为nil。这里多说一点,weak的runtime实现是通过hash表完成的,用变量名做键,一旦发现属性所指的对象被释放了,立刻设置为nil。

  unsafe_unretained:和weak一样,唯一的区别就是当对象被释放后,该属性不会被设置为nil。所以是unsafe的。

  copy:和strong类似,不过该属性会被复制一个新的副本。很多时使用copy是为了方式Mutable(可变类型)在我们不知道的情况下修改了属性值,而用copy可以生成一个不可变的副本防止被修改。如果我们自己实现setter方法的话,需要手动copy。

4.方法名:

  getter = <name>

  setter = <name>

  方法名可以修改为我们合成的方法名,可以使存取方法语义更加符合应用场景。

  如果要在其它属性里面设置属性的话,还是要符合属性特性,比如copy的话我们还是要手动copy一下属性。这里说一下构造方法里需要直接操作实例变量,而不应该调用setter和getter。

对象内部尽量直接访问实例变量

首先说一下构造方法和析构方法中为什么不能使用setter和getter,因为setter和getter是经过我们包装过的方法,有可能增加一些判断,而如果子类调用父类的构造方法同时实现了自己的setter和getter,那么很可能就会出现问题。

通过属性访问实例变量会使用属性的字面语义,会使用KVO所以在执行效率上肯定比直接调用实例变量慢,但是通过属性访问可以截获属性的获取和设置更加方便调试和控制。

一般在类内部推荐设置用setter 获取直接用实例变量。

这里再说一下惰性加载,所谓惰性加载就是指,属性会在第一次调用getter的时候初始化,如下:

-(NSString *)name
{
if (!_name){
_name = [[NSString alloc] init];
}
return _name;
}

那么此时就只能够通过getter来调用实例变量了。

Objective-C—— @Property详解的更多相关文章

  1. Objective-C中的@Property详解

    Objective-C中的@Property详解 @Property (属性) class vairs 这个属性有nonatomic, strong, weak, retain, copy等等 我把它 ...

  2. OC中的@property详解

    简介: @property 生成了变量的get set 方法,同时指定了变量名称. 例如@property (nonatomic,strong) NSString *name;表示生成了_name私有 ...

  3. python property详解

    Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情.在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter ...

  4. Python @property 详解

    本文讲解了 Python 的 property 特性,即一种符合 Python 哲学地设置 getter 和 setter 的方式. Python 有一个概念叫做 property,它能让你在 Pyt ...

  5. @property详解,@property修饰符以及各个修饰符区别(上)

    相信很多参加过面试的人员很多都会被问到:weak与assign的区别,copy与strong的区别.如果你仅仅说一点点copy一般对NSString,weak对于控件的修饰,assign对于基本类型, ...

  6. Objective-c的@property 详解

    转自:http://www.cnblogs.com/andyque/archive/2011/08/03/2125728.html 之前很多网友对我翻译的教程中的Property的使用感到有些迷惑不解 ...

  7. Delphi Property详解

    http://anony3721.blog.163.com/blog/static/51197420107105132120/?ignoreua Property Keyword Defines co ...

  8. python3与django中@property详解

    django提供了内置装饰器 @staticmethod\@classmethod\property 在OSQA中,@property的使用频率是非常高的.下面就是它的使用方法: @property ...

  9. Python之@property详解及底层实现介绍

    转自:https://blog.csdn.net/weixin_42681866/article/details/83376484 前文 Python内置有三大装饰器:@staticmethod(静态 ...

随机推荐

  1. 27.7 并行语言集成查询(PLinq)

    static void Main() { ObsoleteMethods(Assembly.Load("mscorlib.dll")); Console.ReadKey(); } ...

  2. JAVA经典题--死锁案例

    死锁原理: 两个线程相互等待对方释放同步监视器 例子程序: public class TestDeadLock implements Runnable { public int flag = 1; s ...

  3. 周记之A Fresh Start(2018/9/2-2018/9/8)

    新学期.新开始.新面貌.新姿态.新目标.新动力……希望自己不忘初心,在自己的地图上摸索自己的路,然后一直走下去,永不回头.在此平台立下一个flag:至少每周一记,包括本周内所做所想所感所悟,继而更加坚 ...

  4. BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

    好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...

  5. 清北学堂模拟赛d1t6 或和异或(xor)

    题目描述 LYK最近在研究位运算,它研究的主要有两个:or和xor.(C语言中对于|和^) 为了更好的了解这两个运算符,LYK找来了一个2^n长度的数组.它第一次先对所有相邻两个数执行or操作,得到一 ...

  6. 【ACM】nyoj_106_背包问题_201308152026

    背包问题时间限制:3000 ms  |  内存限制:65535 KB 难度:3描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10 ...

  7. [bzoj1598][Usaco08Mar]牛跑步_A*_Dijkstra

    牛跑步 bzoj-1598 题目大意:给你n个点,m条边的有向图.求从1到n的严格的第k短路. 注释:$1\le n\le 1000$,$1\le m \le 10,000$,$1\le k \le ...

  8. c++ 11 thread 初试

    最新的 c++11标准整合进了 线程支持.以下写一个小程序測试一下. 測试代码: #include <iostream> #include <thread> void hell ...

  9. NSThread/NSOperation/GCD 三种多线程技术

    1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ...

  10. Eclipse如何导入第三方jar包

    本文转自:http://blog.csdn.net/mazhaojuan/article/details/21403717  我们在用Eclipse开发程序的时候,经常要用到第三方jar包.引入jar ...