zoukankan      html  css  js  c++  java
  • Objective-C 中类属性(修饰)

    Objective-C 中类属性(修饰)

     (2013-07-13 14:38:35)
    标签: 

    it

    分类: IOS笔记
    nonatomic: 非原子性访问,对属性赋值的时候不加锁,多线程并发访问会提高性能。若不加此属性,则默认是两个访问方法都为原子型事务访问。
    (atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。)

    assign: 简单赋值,不更改引用计数;
            适用于基本数据类型(例如NSInteger)和C数据类型(int,float,double,char,等)以及指针的弱引用
    注:指针的弱引用,比如:delegate,在ARC模式中用weak比较好,在非ARC模式中用assign

    一、非ARC模式
    copy: 建立一个索引计数为1的对象,然后释放旧的对象

    retain: 释放旧的对象,将旧的对象的值赋予输入对象,在提高输入对象的索引计数为1

    例子:
    @interface MyClass:NSObject
    @property (nonatomic, copy) NSString *myString;
    这里定义了一个NSString类型的属性,不需要原子操作,所以用nonatomic.
    为什么需要copy,而不是retain呢! 因为如果对myString赋值原字符串是一个可变的字符串(NSMutableString)对象的话,用retain的话,当原字符串改变的时候你的myString属性也会跟着变掉。我想你不希望看到这个现象。

    @property (nonatomic, retain) UIView *myView;
    这里定义了一个UIView类型的属性,不需要原子操作,所以用nonatomic.
    当对myView 赋值的时候原来的UIView对象retainCount会加1

    @implementation MyClass


    @synthesize myString;
    @synthesize myView;

    创建一个MyClass的对象

    MyClass *object=[[MyClass allocinit];
    NSMutableString *mutString=[NSMutableString stringWithString:"hello"];
    object.myString=mutString;
    [mutString appendString:@"world!"];
    NSLog(@"%@",mutString); 输出为“hello world!”;
    NSLog(@"%@",object.myString); 输出为"hello",因为myString在mutString改变之前已经copy了一份副本

    UIView *view=[[UIView allocinit];
    view的retainCount为1;

    object.myView=view;
    此时view的retainCount为2,因为myView对View进行了一次retain。

    [view release];
    此处虽然view被release释放掉了,但是myView对view进行了一次retain,那么myView保留的UIView的对象指针仍然有效。
    [object release];

    二、ARC模式

     iOS中的ARC是随着xcode4.2一起引入的,4.2版本以前的xcode是没有这种特性的,ARC只能在iOS4 和iOS5上使用,而weak关键字只能在iOS5上使用,并且只能是工程在ARC管理内存的时候才能用。
            前段时间看到别人的代码中出现了unsafe_unretained的关键字,虽然自己了解它是出自arc中的关键字,但是为了了解的更加透彻,所以上网收集了一些相关知识来记录一下,以备以后查阅;
    先 来了解一下各个关键字之间的关系,和其是否拥有所有权(及保留)属性值关键字所有权strong __strong有weak__weak无unsafe_unretained__unsafe_unretained无copy__strong有 assign__unsafe_unretained无retain__strong有

    strong
    该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者。

    weak
    该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被破弃之后,对象将被自动赋值nil。
    并且,delegate 和 Outlet 应该用 weak 属性来声明。同时,iOS 5 之前的版本是没有 __weak 关键字的,所以 weak 属性是不能使用的。这种情况我们使用 unsafe_unretained。

    unsafe_unretained
    等效于__unsafe_unretaind关键字声明的变量;像上面说明的,iOS 5之前的系统用该属性代替 weak 来使用。
    (这里需要说明一下:应尽量不要使用unsafe_unretained来声明属性,因为如果它所指向的对象被释放了,那么它将变成一个野指针,而不会是nil,如果程序试图访问该野指针就会造成crash)

    copy
    与 strong 的区别是声明变量是拷贝对象的持有者。

    assign
    一般Scalar Varible用该属性声明,比如,int, BOOL。

    retain
    该属性与 strong 一致;只是可读性更强一些。

    读写相关的属性 (readwrite, readonly)
    读写相关的属性有 readwrite 和 readonly 两种,如果使用ARC之后,我么需要注意一下 readonly 属性的使用。

    比如下面的变量声明。
    @property (nonatomic, readonly) NSString *name;
    一般声明为 readonly 的变量按理说应该不需要持有所有权了,但是在ARC有效的情况下,将出现下面的错误信息 :
    ARCforbidssynthesizingapropertyofanObjective-C object with unspecified ownership or storage attribute 如果定义了ARC有效,那么必须要有所有者属性的定义;所以我们的代码改成这样,就OK了
    @property (nonatomic, strong, readonly) NSString *name;
    不过有一点,Scalar Varible的变量缺省都有 assign 的属性定义,所以不需要给他们单独的明示声明了。

    有一个关键字需要特别注意一下,就是__autoreleasing
    在没有开启ARC的情况下,我们可以在一个函数中使用autorelease让某个对象延迟释放,但是在开启ARC的情况下是不会通过编译,如下:

    -(ClassA *)TestMethod{ ClassA *classA = [[ClassA alloc] init]; return [classA autorelease];}

    在开启ARC的情况下,我们就需要使用如下方式进行替代:

    -(ClassA *)TestMethod{ __autoreleasing ClassA *classA = [ClassA alloc] init]; return classA;}

    或:

    -(NSString *)TestMethod:(_autoreleasing ClassA *)classA{ classA = [[ClassA alloc] init]; return classA;}ARC机制让我们节省了很多代码的编写,并且也让程序在效率方面有了很大的提升,所以充分利用这个新特性对我们是非常有帮助的,但是不建议新手使用,因为它会让我们知其然而不知其所以然。
  • 相关阅读:
    107.JsonResponse
    106.HttpResponse对象详解
    前端学习笔记系列一:2 Vue的单文件组件
    前端学习笔记系列一:1.export default / export const
    @vue-cli的安装及vue项目创建
    Github版本控制系统
    C# 篇基础知识11——泛型和集合
    C# 篇基础知识10——多线程
    C# 篇基础知识9——特性、程序集和反射
    C# 篇基础知识8——正则表达式
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4955604.html
Copyright © 2011-2022 走看看