请解释以下keywords的区别: assign vs weak, __block vs __weak

1. 假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a 和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。

2. 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),还是上面的那个例子,我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时引用计数增加到 2。这时如果a不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1。当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。

3. 上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引起1中的问题,当数据为int, float等原生类型时,可以使用assign。retain就如2中所述,使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。
 
4. copy是在你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。



1.assign: 用于非指针变量。用于基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char)另外还有id
       反正记住:前面不需要加 “*” 的就用assign吧,weak 就是相当于assign

2. retian 释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1,用于指针变量。就是说你定义了一个变量,然后这个变量在程序的运行过程中会被更改,并且影响到其他方法。xcode4.3及以后版本上面开发,retian和strong都是一样的,没区别

3. copy :  效果其实和retain没什么两样,唯一的区别就是copy只用于NSString而不能用于NSMutableString,如果当一个类继承NSObject,那么这个类里面的属性需要使用copy。

retain是指针拷贝,copy是内容拷贝。





Blocks理解:

Blocks可以访问局部变量,但是不能修改

如果修改局部变量,需要加__block

 __block <span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span> multiplier = <span class="hljs-number" style="color: rgb(42, 161, 152);">7</span>;
     <span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span> (^myBlock)(<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span>) = ^(<span class="hljs-keyword" style="color: rgb(133, 153, 0);">int</span> num) {
         multiplier ++;<span class="hljs-comment" style="color: rgb(147, 161, 161);">//这样就可以了</span>
         <span class="hljs-keyword" style="color: rgb(133, 153, 0);">return</span> num * multiplier;
     };

2、如果局部变量是数组或者指针的时候只复制这个指针,两个指针指向同一个地址,block只修改指针上的内容。如:

<span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSMutableArray</span> *mArray = [<span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSMutableArray</span> arrayWithObjects:<span class="hljs-string" style="color: rgb(42, 161, 152);">@"a"</span>,<span class="hljs-string" style="color: rgb(42, 161, 152);">@"b"</span>,<span class="hljs-string" style="color: rgb(42, 161, 152);">@"abc"</span>,<span class="hljs-literal" style="color: rgb(0, 102, 102);">nil</span>];
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSMutableArray</span> *mArrayCount = [<span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSMutableArray</span> arrayWithCapacity:<span class="hljs-number" style="color: rgb(42, 161, 152);">1</span>];
    [mArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock: ^(<span class="hljs-keyword" style="color: rgb(133, 153, 0);">id</span> obj,NSUInteger idx, <span class="hljs-built_in" style="color: rgb(38, 139, 210);">BOOL</span> *stop){
        [mArrayCount addObject:[<span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSNumber</span> numberWithInt:[obj length]]];
    }];
   
    <span class="hljs-built_in" style="color: rgb(38, 139, 210);">NSLog</span>(<span class="hljs-string" style="color: rgb(42, 161, 152);">@"%@"</span>,mArrayCount);
<p style="color: rgb(51, 51, 51); margin-top: 0px; margin-bottom: 18px; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif; font-size: 14px; line-height: 22.3999996185303px;">例子里面确实没有修改<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 0.92857em; padding: 2px 4px; color: rgb(199, 37, 78);">mArrayCount</code>这个局部变量啊。<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 0.92857em; padding: 2px 4px; color: rgb(199, 37, 78);">mArrayCount</code>是一个指针,指向一个可变长度的数组。在block里面,并没有修改这个指针,而是修改了这个指针指向的数组。换句话说,<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 0.92857em; padding: 2px 4px; color: rgb(199, 37, 78);">mArrayCount</code>是一个整数,保存的是一块内存区域的地址,在block里,并没有改变这个地址,而是读取出这个地址,然后去操作这块地址空间的内容。</p><p style="margin-top: 18px; margin-bottom: 18px; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif; font-size: 14px; line-height: 22.3999996185303px;"><span style="color: rgb(51, 51, 51);">这是允许的,因为声明block的时候实际上是把当时的</span>临时变量<span style="color: rgb(51, 51, 51);">又复制了一份,在block里即使</span>修改<span style="color: rgb(51, 51, 51);">了这些</span>复制的变量<span style="color: rgb(51, 51, 51);">,也</span>不<span style="color: rgb(51, 51, 51);">影响外面的</span>原始变量<span style="color: rgb(51, 51, 51);">。即</span>所谓的闭包<span style="color: rgb(51, 51, 51);">。</span></p><p style="color: rgb(51, 51, 51); margin-top: 18px; margin-bottom: 18px; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif; font-size: 14px; line-height: 22.3999996185303px;">但是当变量是一个指针的时候,block里只是复制了一份这个指针,两个指针指向同一个地址。所以,在block里面对指针指向内容做的修改,在block外面也一样生效。</p><div style="color: rgb(101, 123, 131);">
</div><span style="color: rgb(101, 123, 131);">
</span>

__weak __typeof(&*self)weakSelf =self; 等同于

__weak UIViewController *weakSelf =self;

为什么不用__block 是因为通过引用来访问self的实例变量 ,self被retain,block也是一个强引用,引起循环引用,用__week是弱引用,当self释放时,weakSelf已经等于nil。

扩展:NSTimer注意避免循环引用的地方,需要找个合适的时机和地方来 invalidate timer

在引用计数的环境里面,默认情况下当你在block里面引用一个Objective-C对象的时候,该对象会被retain。当你简单的引用了一个对象的实例变量时,它同样被retain。但是被__block存储类型修饰符标记的对象变量不会被retain

注意:在垃圾回收机制里面,如果你同时使用__weak和__block来标识一个变量,那么该block将不会保证它是一直是有效的。 如果你在实现方法的时候使用了block,对象的内存管理规则更微妙:也是(__weak与__block区别:)

1、如果你通过引用来访问一个实例变量,self会被retain。
2、如果你通过值来访问一个实例变量,那么变量会被retain



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值