文档章节

分配到弱属性;对象将在赋值之后释放

海二少
 海二少
发布于 2016/05/02 11:19
字数 1427
阅读 44
收藏 0
BirdWatching的iOS app,现在想要去多多折腾,搞懂不同property的setter修饰符:assign,copy,retain等的更深层的含义。
所以,专门去把代码改为:
?
123    //@property (nonatomic, weak) UIImagePickerController *imgPickerController;//@property (nonatomic) UIImagePickerController *imgPickerController;@property (nonatomic, assign) UIImagePickerController *imgPickerController;    
改了之后,结果就是.m文件中初始化的代码:
?
1    self.imgPickerController = [[UIImagePickerController alloc] init];    
出现了警告:
ARC Semantic Issue,Assigning retained object to unsafe property;object will be released after assignment,然后程序运行,也出错了:
 
【解决过程】
1.根据之前的学习,对于assign等setter的含义为:
The Objective-C Programming Language – Declared Properties
Setter Semantics
These attributes specify the semantics of a set accessor. They are mutually exclusive. 
strong
Specifies that there is a strong (owning) relationship to the destination object.
weak
Specifies that there is a weak (non-owning) relationship to the destination object.
If the destination object is deallocated, the property value is automatically set to nil.
(Weak properties are not supported on OS X v10.6 and iOS 4; use assigninstead.)
copy
Specifies that a copy of the object should be used for assignment. 
The previous value is sent a release message.
The copy is made by invoking the copy method. This attribute is valid only for object types, which must implement the NSCopying protocol.
assign
Specifies that the setter uses simple assignment. This attribute is the default.
You use this attribute for scalar types such as NSInteger and CGRect.
retain
Specifies that retain should be invoked on the object upon assignment.
The previous value is sent a release message.
In OS X v10.6 and later, you can use the __attribute__ keyword to specify that a Core Foundation property should be treated like an Objective-C object for memory management:
@property(retain) __attribute__((NSObject)) CFDictionaryRef myDictionary;
所以,此处代码改为:
?
1    @property (nonatomic, assign) UIImagePickerController *imgPickerController;    
后,加上之前对于assign的学习,知道了此处对于assign,首先是只适用于非对象类的数据,比如NSInteger,也就是,对于对象引用计数的话,没有任何改变。
所以,上述的初始化代码部分中的:
[[UIImagePickerController alloc] init];
得到了一个UIImagePickerController,然后赋值给了
self.imgPickerController
但是要知道,此处的self.imgPickerController由于是assign,所以没有对于上述得到的UIImagePickerController引用计数增加,即没有打算再用到UIImagePickerController,所以刚生成的UIImagePickerController,因为没有人再用刀它,就自动释放掉了。所以后续对于self.imgPickerController的操作,都是在操作一个没有分配实体对象的空的指针,所以肯定都是无效操作,肯定就会出现EXC_BAD_ACCESS错误了。
就是之前C语言中的野指针的意思了,只是有个指针变量而已,而指针所指向的物理内存,早已被释放掉了,所以你再继续操作此块物理内存,就会出现异常操作了。
 
2.对应的,去改为:
?
1234    //@property (nonatomic, weak) UIImagePickerController *imgPickerController;//@property (nonatomic) UIImagePickerController *imgPickerController;//@property (nonatomic, assign) UIImagePickerController *imgPickerController;@property (nonatomic, retain) UIImagePickerController *imgPickerController;    
然后运行结果就是OK的了。
 
3.相应的,也基本明白了,之前对于写成weak的话:
?
1234    @property (nonatomic, weak) UIImagePickerController *imgPickerController;//@property (nonatomic) UIImagePickerController *imgPickerController;//@property (nonatomic, assign) UIImagePickerController *imgPickerController;//@property (nonatomic, retain) UIImagePickerController *imgPickerController;    
然后对于此处的和imgPickerController全部相关的代码是:
?
12345678910111213141516171819    - (void)viewDidLoad{    self.imgPickerController = [[UIImagePickerController alloc] init];    self.imgPickerController.delegate = self; }     //handle the tap to image-(void)handleImageTap:(UITapGestureRecognizer *)sender{         if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])    {        NSArray *availableMediaTypeArr = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];                 self.imgPickerController.mediaTypes = availableMediaTypeArr;        [self presentViewController:self.imgPickerController animated:YES completion:NULL];    }}    
其中,运行到handleImageTap的时候,在view画面切换的时候:
?
1    [self presentViewController:self.imgPickerController animated:YES completion:NULL];    
程序会出错。
所以,内部的逻辑,应该是:
最开始用:
?
1    self.imgPickerController = [[UIImagePickerController alloc] init];    
初始化后,就是一个weak弱引用了,意思是,如果后者,即alloc的UIImagePickerController被dealloc的话,
那么前者self.imgPickerController就自动设置为nil了。
但是由于当前程序,显示控件中,一直使用到了UIImagePickerController,所以一直也没什么问题。
但是当调用presentViewController画面切换的时候,就自动去dealloc释放了,那个引用为0的,之前alloc的UIImagePickerController,所以,导致此时self.imgPickerController也就自动变为nil了。
所以程序会出错了。
4.对应的,当程序再改为:
?
1234    //@property (nonatomic, weak) UIImagePickerController *imgPickerController;@property (nonatomic) UIImagePickerController *imgPickerController;//@property (nonatomic, assign) UIImagePickerController *imgPickerController;//@property (nonatomic, retain) UIImagePickerController *imgPickerController;    
后,此时默认的是strong,即owning的效果了,所以引用计数为1了,所以即使画面切换,由于self.imgPickerController对于UIImagePickerController的引用计数还是1,没有变为0,所以,后续的self.imgPickerController指针指向的,是真正存在的UIImagePickerController对象,所以程序可以正常执行的。
即默认的strong和retain的效果是一致的。
5.对应的,后来也看到:
iOS 5中的strong和weak关键字 
中说,weak相当于assign,strong相当于retain,但是看着还是很晕。
6.最后看到这里:
Weak and strong property setter attributes in Objective-C
解释的很清楚:
对于单个文件,根据设置,可以开启或关闭ARC。
如果用了ARC,则不能使用retain,release,autorelease等等修饰符,而只能:
针对属性property,使用weak,strong;
针对变量variable,使用__weak,__strong;
strong等价于retain;
weak等价于assign;
 
只有一种情况下需要用到weak:
当你想要避免循环引用的时候,才会考虑用weak;
因为如果都用strong的话,有可能出现,父类retain子类,而子类retain父类,即循环引用了,导致两者始终都无法释放。
此时就可以用weak避免此情况。
 
另外还有个toll free bridging的部分,不多解释,有空看官网解释:
Core Foundation Design Concepts – Toll-Free Bridged Types
 
而关于此部分的内容,相关的官网解释,在这里:
Transitioning to ARC Release Notes

【总结】
在对于变量/属性,设置strong还是weak,是assign还是retain,还是copy的时候,需要搞清楚意思,才能设置,不能随便设置,否则很容易导致程序死掉。
对于这部分的内容,目前还没有透彻理解,等有空的话,好好研究一下再总结出来。


本文转载自:http://www.crifan.com/ios_warning_arc_semantic_issue_assigning_retained_object_to_unsafe_property...

海二少
粉丝 0
博文 87
码字总数 48854
作品 0
程序员
私信 提问
理解Android Bitmap

基于android-6.0.1_r80源代码分析 通过下面三个章节基本可以扫清盲区。文章没有覆盖到的一方面是Bitmap用法,这部分建议阅读库源代码。一些的概念,例如,需要具备一定CG物理基础,不管怎样先...

Cc养鱼人
2017/11/27
0
0
Objective-C高级编程笔记一(自动引用计数)

示例代码下载 手动引用计数 MRC内存管理的思考方式 自己生成的对象自己持有 不是自己生成的对象,自己也能持有 不在需要自己持有的对象时释放 不是自己持有的对象无法释放 对象操作与Objecti...

酒茶白开水
04/04
0
0
iOS中结合代码看内存管理(一)

阅读本文前,建议移步先去了解下内存管理相关知识。 1: iOS内存管理机制(百度goole大法可以获得很多推荐)。 2: iOS中的动态内存分配 3: 堆栈的原理:堆栈 百科 1:自动释放池的常见问题: ...

Nlinger
2017/06/07
0
0
OC-基础总结(二)

OC基础总结 重新回过头看这些基础知识,对许多知识点都有新的认识,拥有坚实的基础才能更快的成长。 OC内存管理 - 基础与MRC 内存管理概述 内存管理 内存的作用:存储数据。 1). 如何将数据存...

xx_cc
2017/05/01
0
0
IOS--内存管理 (retain, assign,copy, strong,weak)

引用计数:为了方便管理内存,oc引入了饮用计数,基本原则:谁创建,谁释放 ! 目的:IOS的对象都继承于NSObject, 该对象有一个方法:retainCount ,内存引用计数。 引用计数在很多技术都用到...

Mark_Jiang
2016/01/27
118
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
34分钟前
4
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
4
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
13
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
13
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部