ARC
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, retain) UIView *rview;
@property (nonatomic, retain) UIView *setRView;
@property (nonatomic, retain) UIView *rView1;
@property (nonatomic, weak) UIView *wView1;
@property (nonatomic, weak) UIView *wView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
#pragma mark - retain
UIView *view0 = [[UIView alloc]init]; _rview = view0;
NSLog(@"view0:%@ _rView:%@",[view0 valueForKey:@"retainCount"],[_rview valueForKey:@"retainCount"]);
NSLog(@"view0:%@ _rView:%@",[view0 valueForKey:@"retainCount"],[self.rview valueForKey:@"retainCount"]);
// view0:2 _rView:2
// view0:2 _rView:3
UIView *view = [[UIView alloc]init]; self.setRView = view;
NSLog(@"view:%@ _rView:%@",[view valueForKey:@"retainCount"],[_setRView valueForKey:@"retainCount"]);
NSLog(@"view:%@ _rView:%@",[view valueForKey:@"retainCount"],[self.setRView valueForKey:@"retainCount"]);
// view:2 _rView:2。alloc+1。强引用加1
// view:2 _rView:3
// - (WeakView *)weakView
// {
// return [[_weakView retain] autorelease];
// }
self.rView1 = [[UIView alloc]init];
NSLog(@"_rView1:%zd",CFGetRetainCount((__bridge CFTypeRef)(_rView1)));
NSLog(@"_rView1:%zd",CFGetRetainCount((__bridge CFTypeRef)(self.rView1)));
//_rView1:1
//_rView1:2
#pragma mark - 不懂 为什么是2??????????
UIView *view1 = [[UIView alloc]init];
_wView = view1;
NSLog(@"view1:%zd _wView:%zd",CFGetRetainCount((__bridge CFTypeRef)(view1)),CFGetRetainCount((__bridge CFTypeRef)(_wView)));
// view1:1 _wView:2
//在autoreleasepool中即使不使用autoreleasing修饰符,而用__weak修饰符替代,同样将obj对象注册到了autoreleasepool中。
// 我们整个工程都是在 autoreleasepool里面的
//int main(int argc, char * argv[]) {
// @autoreleasepool {
// return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
// }
//}
// _wView1 = [[UIView alloc]init]; // 在iOS的ARC机制下,任何对象,当没有其他对象对他进行强引用时,都会被自动释放
// NSLog(@"_wView1: retainCount:%zd",CFGetRetainCount((__bridge CFTypeRef)(_wView1)));
// 崩溃
}
@end
MRC
alloc/new/copy/mutableCopy | +1 | 生成并持有对象
retain | +1 | 持有对象
release| -1 | 释放对象
dealloc | - | 废弃对象
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, retain) UIView *rView;
@property (nonatomic, retain) UIView *sView;
@property (nonatomic, weak) UIView *wView;
@property (nonatomic, assign) UIView *aView;
@end
@implementation ViewController
- (void)dealloc {
[_rView release];
[_sView release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
#pragma mark - retain == strong 使用实例变量
UIView *rView = [[UIView alloc]init];
_rView = rView;
NSLog(@"rView:%zd _rView:%zd",rView.retainCount, _rView.retainCount); // rView:1 _rView:1
_rView = [[UIView alloc]init];
NSLog(@"_rView:%zd",_rView.retainCount); // _rView:1
#pragma mark - 调用set方法
UIView *sView = [[UIView alloc]init];
self.sView = sView;
NSLog(@"sView:%zd _sView:%zd",sView.retainCount, _sView.retainCount); // sView:2 _sView:2
self.sView = [[UIView alloc]init];
NSLog(@"_sView:%zd",_sView.retainCount); // _sView:2
// ????? 原因:必须了解MRC下set方法是怎么写的 内部进行retain操作 所以引用计数加1
// -(void)setString:(NSString*)string
// {
// [string retain];
// [_string release];
// _string =string;
// }
#pragma mark - assign set方法直接赋值 内部没有retain操作
UIView *aView = [[UIView alloc]init];
_aView = aView;
NSLog(@"aView:%zd _aView:%zd",aView.retainCount, _aView.retainCount); // view:1 _rView:1
_aView = [[UIView alloc]init];
NSLog(@"_aView:%zd",_aView.retainCount); // _wView1:1
#pragma mark - weak set方法直接赋值 _wView 使用一次引用计数加1
UIView *wView = [[UIView alloc]init];
_wView = wView;
NSLog(@"wView:%zd",wView.retainCount); // view:1
NSLog(@"wView:%zd",wView.retainCount); // view:1
NSLog(@"wView:%zd",wView.retainCount); // view:1
NSLog(@"wView:%zd",wView.retainCount); // view:1
NSLog(@"wView:%zd",wView.retainCount); // view:1
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:1 _rView:2
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:2 _rView:3
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:3 _rView:4
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:4 _rView:5
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:5 _rView:6
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:6 _rView:7
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:7 _rView:8
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:8 _rView:9
NSLog(@"wView:%zd _wView:%zd",wView.retainCount, _wView.retainCount); // view:9 _rView:10
_wView = [[UIView alloc]init];
NSLog(@"_wView1:%zd",_wView.retainCount); // _wView1:2
// 对象被注册到 autoreleasepool 中
// 1、当方法名不是alloc/new/copy/mutableCopy时,使用return返回的对象强引用会被自动注册到
// 2.访问附有__weak修饰符的变量时,该变量会被自动注册到autoreleasepool中
// 原因是__weak修饰符支持有对象的弱引用,在访问引用对象的过程中,该对象可能被释放。而如果将该对象加入到autoreleasepool中,在pool被释放之前,tmp对该对象的引用都是有效的
}
@end
在从App Store上下载Xcode后,默认是不会安装command Line Tools的,Command Line Tools是在Xcode中的一款工具,可以在命令行中运行C程序
安装:在终端中输入以下命令:xcode-select --install ,按回车。
如果上述测试 在 command Line Tools下面测试那么正常
在ARC下,编译器会检查方法名是否以alloc/new/copy/mutableCopy开头,如果不是,则自动将返回的对象注册到autorelease pool中
原因
ARC下使用__weak修饰符的变量时,该变量会被自动注册到autoreleasepool中在autoreleasepool中即使不使用autoreleasing修饰符,而用__weak修饰符替代,同样将obj对象注册到了autoreleasepool中,使得引用计数加1。而上面代码是创建main函数的时候已经把所有的代码加入到了autoreleasepool中
当一个对象被释放之后,它所在的内存应该是不能被访问的,所以是永远不可能出现retainCount打印出来为0的情况的。可是为什么会出现1呢?
其实这一直是一个未确定的问题,或许只有苹果自己才知道它的真正原因,不过iOS程序员们更愿意相信,是因为这一块内存地址的内容还没有被其他内容复写,所以还可以错误地访问
参考这段代码
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, assign) NSObject *aObject;
@property (nonatomic, weak) NSObject *wObject;
@end
@implementation Person
- (instancetype)init {
if (self = [super init]) {
NSObject *object = [[NSObject alloc]init];
NSLog(@"object: %ld",[object retainCount]); // object: 1
_aObject = object;
NSLog(@"object: %ld",[object retainCount]);// object: 1
NSLog(@"_aObject: %ld",[_aObject retainCount]);// object: 1
_wObject = object;
NSLog(@"object: %ld",[object retainCount]);// object: 1
NSLog(@"_wObject:%ld",[_wObject retainCount]);// object: 2
}
return self;
}
//重写父类的dealloc方法
-(void)dealloc{
NSLog(@"%s",__func__);
[super dealloc];
}
@end
int main(int argc, const char * argv[]) {
Person *per1 = [[Person alloc]init];
[per1 release];
return 0;
}
weak 可以参考
上述问题的原因
ARC下面的内存管理
ARC下的autorelease
NSString引用计数
alloc init 引用计数
iOS内存管理(MRC、ARC)深入浅出
ObjectiveC高级编程iOS与OSX多线程和内存管理
网友评论