iOS ARC - 弱而强的属性

RGM*_*GML 5 iphone weak retain automatic-ref-counting

我试图了解ARC的工作方式,据我所知,我应该在这里做错事.这是我正在使用的代码:

接口:

@interface ViewController : UIViewController{

}

@property (strong, nonatomic) NSString * myString ; 
@property (weak, nonatomic) NSString * myPointer ;
Run Code Online (Sandbox Code Playgroud)

执行:

 - (void)viewDidLoad{

     [super viewDidLoad];
     self.myString = @"Hello world!" ; // myString is strong
     self.myPointer = self.myString ; // myPointer var is weak

     [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
     [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

 - (void) makeNilMyValue{
     self.myString = nil ; 
}

 - (void) printValues{
     NSLog(@"myString: %@", self.myString) ;
     NSLog(@"myPointer: %@", self.myPointer) ; 
 }
Run Code Online (Sandbox Code Playgroud)

执行此操作后,我得到:

2012-02-26 11:40:41.652 test1[933:207] myString: (null)

2012-02-26 11:40:41.653 test1[933:207] myPointer: Hello world!
Run Code Online (Sandbox Code Playgroud)

如果我没错,由于myPointer很弱,它不应该保留对象的内容.所以,它应该显示nil而不是"Hello World!".

我究竟做错了什么?

在Caleb的回答之后,我创建了另一个弱指针,请参阅下面的代码:

- (void)viewDidLoad{
    [super viewDidLoad];
    self.myString = @"Hello world!" ; // myString is strong
    self.myPointer = self.myString ; // myPointer var is weak
    self.myPointer2 = self.myString ; // myPointer2 var is weak

    [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
    [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

- (void) makeNilMyValue{
    self.myPointer2 = @"value changed!" ;
    self.myString = nil ;

}

- (void) printValues{
    NSLog(@"myString: %@", self.myString) ;
    NSLog(@"myPointer: %@", self.myPointer) ;
}
Run Code Online (Sandbox Code Playgroud)

关键是我仍然得到了以前的答案:

2012-02-26 12:08:13.426 test1[1333:207] myString: (null)
2012-02-26 12:08:13.427 test1[1333:207] myPointer: Hello world!
Run Code Online (Sandbox Code Playgroud)

Jir*_*iri 8

正如Caleb指出的那样,在这个例子中使用常量NSString并不是一个好主意.

在源代码中创建字符串对象的最简单方法是使用Objective-C @"..."构造:

NSString*temp = @"/ tmp/scratch"; 请注意,以这种方式创建字符串常量时,应避免使用除7位ASCII字符之外的任何内容.这样的对象是在编译时创建的,并且在整个程序的执行过程中都存在.编译器使这些对象常量在每个模块的基础上是唯一的,并且它们永远不会被释放,尽管您可以像执行任何其他对象一样保留和释放它们.您还可以像执行任何其他字符串一样将消息直接发送到字符串常量:

BOOL same = [@"comparison"isEqualToString:myString];

该文件解释说,常量字符串永远不会消失.

尝试使用其他东西进行实验.我尝试了NSObject,它产生了预期的结果.

接口:

@interface ViewController : UIViewController

@property (strong, nonatomic) NSObject * myString; 
@property (weak, nonatomic) NSObject * myPointer;

@end
Run Code Online (Sandbox Code Playgroud)

执行:

@implementation ViewController

@synthesize myString = _myString;
@synthesize myPointer = _myPointer;

- (void)viewDidLoad{

    [super viewDidLoad];

    self.myString = [[NSObject alloc] init];
    self.myPointer = self.myString;
    self.myString = nil; 
    NSLog(@"myString: %@", self.myString);
    NSLog(@"myPointer: %@", self.myPointer);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end
Run Code Online (Sandbox Code Playgroud)

当没有强大的内存指针时,弱指针被设置为nil,如文档中所述 - Apple Developer或llvm.

__weak指定不使引用对象保持活动状态的引用.当没有对象的强引用时,弱引用设置为nil.


Cal*_*leb 5

所以,它应该显示nil而不是"Hello World!".

常量字符串永远不会被释放,所以你的`@"Hello World!" 永远不会消失.这就是为什么你的弱引用永远不会设置为nil.

  • 当目标被解除分配时,弱引用被设置为nil.这是ARC的一个特性 - 合成的弱属性永远不会持有悬空指针. (5认同)