Objective-C—— @Property详解

实例变量:
属性其实说直白点就是 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标记的,这是因为子类的某些属性不是

属性特性(语义)

属性的特质分为四类:

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来调用实例变量了。

时间: 2024-08-05 07:06:04

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

iOS 学习笔记——0004(@property详解)

这里以一个Person类进行举例: @interface Person : NSObject { ... } @property(nonatomic,copy)NSString* name; @end @property 做了三件事 1.大括号中(如上图的大括号),声明变量,变量前加_,这里是_name 2.生成对应的get方法 3.生成对应的set方法 可以在实现文件中,重写get,set方法 这里需要注意:如果get,set方法都是自己写的话,那么在大括号中的变量声明也需要自己写了 写到这里

【转】Objective-C语法property详解

1.简介: property是Objective-C的关键词,与@synthesize配对使用,用来让编译好器自动生成与数据成员同名的方法声明.@synthesize则是用来生成对应声明方法的实现. 1.1 property的语法格式: @property (参数1,参数2)类型名字: 这里的参数,主要有以下三种: setter/getter方法(assign/retain/copy) 读写属性(readwrite/readonly) atomicity(nonatomic) 1.2 三种方式的

iOS复习笔记6:property详解

@property type xxx 可以自动生成一个type _xxx;成员变量: 同时还生成对应的setter和getter方法. 可以通过以下四种类型的参数,控制生成getter和setter方法. 1 set方法内存管理参数 1.1 assign: 默认值,直接赋值,使用于基础数据类型 1.2 retain: release旧值,retain新值,再赋值 1.3 copy  : release旧值,copy新值 2 是否要生成setter方法的参数 2.1 readwrite: 默认值,

IOS开发之property详解

之前很多网友对我翻译的教程中的Property的使用感到有些迷惑不解,搞不清楚什么时候要release,什么时候要self.xxx = nil;同时对于Objective-c的内存管理以及cocos2d的内存管理规则不够清楚.本文主要讲解objc里面@property,它是什么,它有什么用,atomic,nonatomic,readonly,readwrite,assign,retain,copy,getter,setter这些关键字有什么用,什么时候使用它们.至于Objc的内存管理和cocos

property详解

下面我们来看一段java代码: class Person{ private name;//把name设为私有属性 private age;//把age设为私有属性 public String getName(){ return name } public setName(String name){ this.name=name } public int getAge(){ return age } public setAge(int age){ this.age=age } } 我们只能通过相应

Python @property 详解

本文讲解了 Python 的 property 特性,即一种符合 Python 哲学地设置 getter 和 setter 的方式. Python 有一个概念叫做 property,它能让你在 Python 的面向对象编程中轻松不少.在了解它之前,我们先看一下为什么 property 会被提出. 一个简单的例子 比如说你要创建一个温度的类Celsius,它能存储摄氏度,也能转换为华氏度.即: class Celsius: def __init__(self, temperature = 0):

黑马程序员——@property及其参数的详解

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ @property详解 1.什么是@property? @property是OC特有的一个关键字,它属于编译器一个特性,编译器碰到@property时,会自动展开为成员变量的set和get方法 在Xcode4.5之前,Xcode编译器碰到@property会将其转换为成员变量set.get方法的声明,碰到@synthesize会展开为成员变量set.get方法的实现,所以XCode4.5之前,@

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

关于@property后面修饰符详解

关于@property后面修饰符详解 @property后面有哪些修饰符 1.线程安全的 atomic.nonatomic 2.访问权限的 readonly.readwrite 3.内存管理(ARC) assign.strong.weak.copy 4.内存管理(MRC) assign.retain.release 5.指定方法名称 (如何定义set get 方法) setter = getter = 由于将来我们经常需要定义一些方法来操作成员变量,而每个方法都必须有一个有意义的名称,而想名字非