一:@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. ubuntu16.04安装Ros(kinetic版本)【亲测好用】

    准备 1.ubuntu16.04 64位桌面版 ps:关于系统的下载和安装这里不做介绍,请自行百度,不是介绍重点 2.更改源 图上的几个勾默认是选上的,如果没有选上,选成上图这样(如果修改过勾,点击关 ...

  2. LoRaWAN_stack移植笔记(四)__RTC

    stm32相关的配置 由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱 ...

  3. poium测试库之JavaScript API封装原理

    poium一直我在维护的一个开源项目,它的定位是以极简的方式在自动化项目中Page Objects设计模式.我在之前的文章中也有介绍. 本篇文章主要介绍一个JavaScript元素操作的封装原理. 为 ...

  4. ASP.NET Core Basic 1-1 WebHost与项目配置

    .NET Core ASP.NET Core Basic 1-1 本节内容为WebHost与项目配置 项目配置文件 我们可以很清楚的发现在我们的文件中含有一个Json文件--appsettings.j ...

  5. (五十五)c#Winform自定义控件-管道

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  6. 在Azure云上实现postgres主备切换

    以下是工作上实现postgres主备切换功能所用到的代码和步骤,中间走了不少弯路,在此记录下.所用到的操作系统为centos 7.5,安装了两台服务器,hostname为VM7的为Master,VM8 ...

  7. 洛谷 P1640 【连续攻击游戏】

    question bank :luogu question Number :1640 title :Continuous attacking game link :https://www.luogu. ...

  8. ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (60000, 28, 28)

    报错 Traceback (most recent call last): File "D:/PyCharm 5.0.3/WorkSpace/3.Keras/3.构建各种神经网络/3.CNN ...

  9. electron-vue-webpack引入bootstrap多实例问题Multiple instances of Vue detected!

    在node modules里面找到electron-webpack目录, 修改out->main.js白名单内容,增加 whiteListedModules.add("bootstra ...

  10. 2019 Multi-University Training Contest 8

    2019 Multi-University Training Contest 8 C. Acesrc and Good Numbers 题意 \(f(d,n)\) 表示 1 到 n 中,d 出现的次数 ...