一:@property 后面可以有哪些修饰符?

1:线程安全的:

atomic,nonatomic

2:访问权限的

readonly,readwrite

3:内存管理(ARC)

assign, copy, strong,weak,

4: 内存管理(MRC)

assign,retain,copy

ARC 下,不显式指定任何属性关键字时,默认的关键字都有哪些?

基本数据: atomic,readwrite,assign

普通的 OC 对象: atomic,readwrite,strong

readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak属性的作用分别是什么。

关键字 注释
readwrite 此标记说明属性会被当成读写的,这也是默认属性。
readonly 此标记说明属性只可以读,也就是不能设置,可以获取。
assign 不会使引用计数加1,也就是直接赋值。
retain 会使引用计数加1。
copy 建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝。
nonatomic 非原子性访问,多线程并发访问会提高性能。
atomic 原子性访问。
strong 打开ARC时才会使用,相当于retain。
weak 打开ARC时才会使用,相当于assign,可以把对应的指针变量置为nil。

 
 
 
 

三:1:原子性:非原子性

开发过程中,setter和getter方法处处都在使用,如果使用atomic修饰,setter和getter方法内部会做很多多线程安全的操作,会很占用系统资源,降低系统性能。

所以在平常开发中原子性(线程安全)一般设置为nonatomic,只有在需要安全的地方atomic

说atomic与nonatomic的本质区别其实也就是在setter方法上的操作不同:

nonatomic的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
    if (_currentImage != currentImage) {
        [_currentImage release];
        _currentImage = [currentImage retain];
            
        // do something
    }
}
- (UIImage *)currentImage
{
    return _currentImage;
}

atomic的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
    @synchronized(self) {
        if (_currentImage != currentImage) {
            [_currentImage release];
            _currentImage = [currentImage retain];
                    
            // do something
        }
    }
}

- (UIImage *)currentImage
{
    @synchronized(self) {
        return _currentImage;
    }
}

四:读写访问权限

读写性的控制(readonly,readwrite,setter,getter)

readonly:只读属性,告诉编译器之声明getter方法,而没有setter(只能读取值,不能被赋值)

readwrite:读写属性,告诉编译器,既声明setter又声明getter方法,readwrite是属性读写性控制的默认修饰词

五:内存权限。

1:weak和assign的区别-正确使用weak、assign

很少有人知道weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址数组。更多人的人只是知道weak是弱引用,所引用对象的计数器不会加一,并在引用对象被释放的时候自动被设置为nil。通常用于解决循环引用问题。但现在单知道这些已经不足以应对面试了,好多公司会问weak的原理。weak的原理是什么呢?下面就分析一下weak的工作原理(只是自己对这个问题好奇,学习过程中的笔记,希望对读者也有所帮助)。

weak 实现原理的概括

Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象的地址)数组。

weak 的实现原理可以概括一下三步:

1、初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。

2、添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数, objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。

3、释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。

六:区别

6.1:区别

a.修饰变量类型的区别

weak 只可以修饰对象。如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。

assign 可修饰对象,和基本数据类型。当需要修饰对象类型时,MRC时代使用unsafe_unretained。当然,unsafe_unretained也可能产生野指针,所以它名字是"unsafe_”。

b.是否产生野指针的区别

weak 不会产生野指针问题。因为weak修饰的对象释放后(引用计数器值为0),指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。

assign 如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。

c、相似

都可以修饰对象类型,但是assign修饰对象会存在问题。

d、总结

assign 适用于基本数据类型如int,float,struct等值类型,不适用于引用类型。因为值类型会被放入栈中,遵循先进后出原则,由系统负责管理栈内存。而引用类型会被放入堆中,需要我们自己手动管理内存或通过ARC管理。

weak 适用于delegate和block等引用类型,不会导致野指针问题,也不会循环引用,非常安全。

6.2:copy

a:  怎么用 copy 关键字

NSString、NSArray、NSDictionary 等等经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary.为确保对象中的属性值不会无意间变动,应该在设置新属性值时拷贝一份,保护其封装性.

block,也经常使用 copy,关键字block。

使用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区.

在 ARC 中写不写都行:对于 block 使用 copy 还是 strong 效果是一样的,但是建议写上 copy,因为这样显示告知调用者“编译器会自动对 block 进行了 copy 操作。

b、用@property 声明的 NSString(或 NSArray,NSDictionary)经常使用 copy 关键字,为什么?如果改用 strong 关键字,可能造成什么问题?

因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
如果我们使用是 strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性

c:深浅copy

七:block中copy

1:下面进入主题为什么要用copy去修饰block呢

个人理解:默认情况下,block会存档在栈中(栈是吃了吐),所以block会在函数调用结束被销毁,在调用会报空指针异常,如果用copy修饰的话,可以使其保存在堆区(堆是吃了拉) ,它的生命周期会随着对象的销毁而结束的。只要对象不销毁,我们就可以调用在堆中的block。

在了解block为什么要用copy之前,我们要先了解block的三种类型
NSGlobalBlock:全局的静态block 没有访问外部变量 你的block类型就是这种类型(也就是说你的block没有调用其他外部变量)
NSStackBlock:保存在栈中的block,没有用copy去修饰并且访问了外部变量,你的block类型就是这种类型,会在函数调用结束被销毁 (需要在MRC)
NSMallocBlock 保存在堆中的block 此类型blcok是用copy修饰出来的block 它会随着对象的销毁而销毁,只要对象不销毁,我们就可以调用的到在堆中的block。

2:

2.1:首先,我们要明确一点,为什么要用copy修饰,这是因为在MRC时期,作为全局变量的block在初始化时是被存放在静态区的,这样在使用时如果block内有调用外部变量,那么block无法保留其内存,在初始化的作用域内使用并不会有什么影响,但一但出了block的初始化作用域,就会引起崩溃,使用copy可以将block的内存推入堆中,这样让其拥有保存调用的外部变量的内存的能力。

2.2:(将block存入堆区带来的一个问题,self会持有block的引用,那么在block里使用self会导致循环引用,这也是为什么在MRC和ARC时期要分别用__block和__weak来修饰self的原因)

既然使用copy的原因是为了让Block在初始化作用域外进行正常访问外部变量,那我们就来看使用strong能不能达到这种效果。

3:外部使用了weakSelf,里面使用strongSelf却不会造成循环,究其原因就是因为weakSelf是block截获的属性,而strongSelf是一个局部变量会在“函数”执行完释放。

是为了保证block执行完毕之前self不会被释放,执行完毕的时候再释放。这时候会发现为什么在block外边使用了__weak修饰self,里面使用__strong修饰weakSelf的时候不会发生循环引用?!

4:__block和__weak的区别 2:

4.1:__weak 本身是可以避免循环引用的问题的,但是其会导致外部对象释放了之后,block 内部也访问不到这个对象的问题,我们可以通过在 block 内部声明一个 __strong 的变量来指向 weakObj,使外部对象既能在 block 内部保持住,又能避免循环引用的问题。

4.2:__block 本身无法避免循环引用的问题,但是我们可以通过在 block 内部手动把 blockObj 赋值为 nil 的方式来避免循环引用的问题。

另外一点就是 __block 修饰的变量在 block 内外都是唯一的,要注意这个特性可能带来的隐患。但是__block有一点:这只是限制在ARC环境下。在非arc下,__block是可以避免引用循环的/

4.3:另外,MRC中__block是不会引起retain;但在ARC中__block则会引起retain。所以ARC中应该使用__weak。

5:为什么使用weakSelf

通过 clang -rewrite-objc 源代码文件名 将代码转为c++代码(实质是c代码),可以看到block是一个结构体,它会将全局变量(self)保存为一个属性(是__strong的),而self强引用了block这会造成循环 引用。所以需要使用__weak修饰的weakSelf。

为什么在block里面需要使用strongSelf

6:  MRC使用了retain修饰的block崩溃掉了,当将MRC切换回ARC,并且把修饰符换为strong时,并没有发生崩溃,说明该block被推入了堆,拥有了保存外部变量内存的能力。

 
7:MRC和ARC下的block
  • 如果是ARC(自动)在堆区 NSMallocBlock
  • 如果是MRC(手动)在栈区 NSStackBlock

8:__block修饰变量在block内部改变其变量值的原理

Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。__block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中。进而在block内部也可以修改外部变量的值。

9:不过在声明Block时,使用strongretain会有截然不同的效果。strong会等于copy,而retain竟然等于assign

10:【在ARC下】:似乎已经没有栈上的block了,要么是全局的,要么是堆上的。有一个特殊情况:如果仅仅定义了block没有赋值给变量的话,仍是在栈上,

【在非ARC下】:存在这栈、全局、堆这三种形式。

01 (OC)* @property 后面可以有哪些修饰符?的更多相关文章

  1. @property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?

    出题者简介: 孙源(sunnyxx),目前就职于百度 整理者简介:陈奕龙(子循),目前就职于滴滴出行. 转载者:豆电雨(starain)微信:doudianyu 属性可以拥有的特质分为四类: 原子性- ...

  2. @property后面可以有哪些修饰符?

    原子性---nonatomic特质 如果不写默认情况为atomic(系统会自动加上同步锁,影响性能) 在iOS开发中尽量指定为nonatomic,这样有助于提高程序的性能 读/写权限---readwr ...

  3. 张超超OC基础回顾_05 property修饰符,id类型,instancetype。。。

    一.property 如果给一个属性同时提供了getter/setter方法, 那么我们称这个属性为可读可写属性 如果只提供了getter方法, 那么我们称这个属性为只读属性 如果只提供了setter ...

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

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

  5. OC基础之访问修饰符

    做C#.Java的人都知道private.protect.public这些访问权限,在OC中看项目基本都没用到这些,昨天就好奇的仔细了解了下,其实OC中也是有这些访问权限的修饰.说实话有好多做过编程的 ...

  6. OC继承以及实例变量修饰符

    这里基本上跟java一样 所以就简单写几点要注意的: 1)OC与java一样都只支持单继承可以多层继承(java单继承多实现) 2) OC中的实例变量修饰符前要加 @ 例如 @private 例如下面 ...

  7. @property的4类修饰符

    一.读写性修饰符:readwrite | readonly readwrite:表明这个属性是可读可写的,系统为我们创建这个属性的setter和getter方法. readonly:表明这个属性只能读 ...

  8. 四.OC基础--1.文档安装和方法重载,2.self和super&static,3.继承和派生,4.实例变量修饰符 ,5.私有变量&私有方法,6.description方法

    四.OC基础--1.文档安装和方法重载, 1. 在线安装 xcode-> 系统偏好设置->DownLoads->Doucument->下载 2. 离线安装 百度xcode文档 ...

  9. @property修饰符

    @property修饰符 修饰是否生成getter方法的 readonly 只生成setter方法,不生成getter方法 readwrite 既生成getter 又生成setter方法(默认) @p ...

随机推荐

  1. 使用 Docker 部署 Spring Boot

    Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常简单,这篇文章我们就来简单学习下. 首先构建一个简单的 Spring Boot 项目, ...

  2. Linux安装配置Samba共享文件系统

    Samba共享文件系统搭建与配置: 1.Samba服务端:yum install samba samba-client cifs-utilscd /etc/samba/cp smb.conf smb. ...

  3. Mybatis多表查询之一对一查询的多种实现-XML配置

    Mybatis 中对于多表查询提供了非常强大的实现方式,主要是通过resultMap的结果映射对于多表查询后的返回值进行封装,让我们来看一下官网上对于resultMap的解释:resultMap 元素 ...

  4. 【数据结构】9.java源码关于HashTable

    1.hashtable的内部结构 基础存储数据的hash桶由Entry结构的数组存放而entry数据结构,有hash,key和value,还有一个指向下一个节点的引用next对象 这里就和hashma ...

  5. centos7不能连接外网

    1.  首先保证虚拟机是NAT模式 2.  打开cmd窗口,输入ipconfig,查看vmnet8的ipv4地址是多少,DNS也需要记下,后面会用到 注意:vmnet8的ip要与虚拟机的网关IP在同一 ...

  6. 详解javascript中的this的指向问题

    首先,要明白this 既不指向函数自身,也不指函数的词法作用域.this一般存在于函数中,表示当前函数的执行上下文,如果函数没有执行,那么this没有内容,只有函数在执行后this才有绑定. 然后,我 ...

  7. 过滤掉Abp框架不需要记录的日志

    该文章是系列文章 基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业 的其中一篇. 问题 ABP.WindowsService/Demo.MyJob/4.0.0该项目不仅 ...

  8. 【Linux命令】nohup命令

    nohup命令 不挂断的运行,它会使您的脚本被忽略SIGHUP,并重定向stdout/stderr到一个文件nohup.out,以便在您注销后该命令可以在后台继续运行. 1)语法 nohup Comm ...

  9. 实参&形参

    实参VS形参 1.实参 argument 实际参数,在函数调用的时候,传递给函数的参数.实参-按值调用 实际参数可以是变量.常量.表达式以及函数 实际参数必须得有确定的值(赋值.输入等),在函数调用时 ...

  10. POJ-2387 Til the Cows Come Home ( 最短路 )

    题目链接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...