美文网首页
weak引用计数问题

weak引用计数问题

作者: Rumbles | 来源:发表于2018-08-08 17:48 被阅读26次

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多线程和内存管理

retain 可以参考

Retain特质属性在MRC中的陷阱以及ARC中对其的规避

相关文章

  • weak引用计数问题

    ARC MRC 原因 ARC下使用__weak修饰符的变量时,该变量会被自动注册到autoreleasepool中...

  • weak、strong、@ property

    面试题:weak实现原理? 一、weak weak 基本用法 weak 是弱引用,用 weak 来修饰、描述所引用...

  • ndk开发-4 引用类型

    三种类型 global local Weak 引用 global引用 Weak引用

  • weak底层实现原理

    一、weak基本用法 weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会加1,而且weak会在引用对...

  • iOS weak修饰属性的原理

    一、weak基本用法 weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会加1,而且weak会在引用对...

  • iOS 内存管理 (4):Weak

    一、weak基本用法 weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会加1,而且weak会在引用对...

  • iOS weak 原理

    一、weak 基本用法weak 是弱引用,用 weak 来修饰、描述所引用对象的计数器并不会增加,而且 weak ...

  • iOS 内存管理(六)-weak原理

    一、基本用法 weak 是弱引用,用 weak 来修饰、描述所引用对象的计数器并不会增加,而且 weak 会在引用...

  • 以弱引用避免保留环--Effective笔记

    1,将某些引用设为weak,可避免出现“保留环”。父引用子 强引用(strong) 子引用父 弱引用(weak...

  • ARC机制中对象的内存引用规则

    Strong与Weak的区别? strong为强引用,weak为弱引用。 (weak和strong)不同的是 当一...

网友评论

      本文标题:weak引用计数问题

      本文链接:https://www.haomeiwen.com/subject/seexbftx.html