iPhone开发学习-从手动计数到Automatic Reference Counting

 

在最新的LLVM编译器中,用ARC,我们将要面新的存特性: strong, weak,   unsafe_unretained,每ARC下的象都要遵循些新特性,出他简单
strong
 strong型的retained将会在他的整生命周期里有效直到该对象被自放。如同其他的Objective-c普通存管理方法一该关键retain方法相似。

weak
种简单的弱关联(zeroing weak referencing),如果一个变量被定义为weak当该变量指dealloc该变将会赋值nil例如,如果有一strong型的string成和一weak型的string成,同时将strong型成值赋给weakstring(指针传递),strong型的stringdeallocweak型的成值时会返回nil。

unsafe_unretained
是一个简单的方法个变量指向其他量。这样并retain前的象,只是简单assign象。一般默的,所有的量都是strong型。作为对比,成员变量必明确的指出型。也就是编译器不多管事的认为所有的成员变量默认为strong性。假两个员变 string1和string2:

#import <UIKit/UIKit.h>

@interface Moving_from_Manual_Reference_Counting_to_ARCAppDelegate :UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, strong) NSString *string1; 

@property (nonatomic, strong) NSString *string2;

@end


在如果我用“String 1”初始化成string1赋值给 string2,我们会看到strong型的string2在string1 dealloc后仍然能保持他的

#import"Moving_from_Manual_Reference_Counting_to_ARCAppDelegate.h"

@implementation Moving_from_Manual_Reference_Counting_to_ARCAppDelegate

@synthesize window = _window; 

@synthesize string1; 

@synthesize string2;

- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

self.string1 = @"String 1"; 

self.string2 = self.string1;

self.string1 = nil;

NSLog(@"String 2 = %@", self.string2);

self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen]bounds]];

self.window.backgroundColor = [UIColor whiteColor]; [self.windowmakeKeyAndVisible];

return YES;

}


:String 2 = String 1

  strong,weak,  unsafe_unretained 繁的用于明成员属性,可以些新的关键来声明本地成,但是要明确的分他的不同。关键字的内联等同于“__关键字”如__strong,__weak,__unsafe_unretained.(注意关键字前面都有两个划线)下面是例子:

- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

/* All local variables are by default strong so just emphasis that. Wereally don't have to mention __strong for the first variable but to make itclear, we will set it. No harm in doing so. */

__strong NSString *yourString =@"Your String";

__weak NSString *myString = yourString; 

yourString = nil; 

__unsafe_unretained NSString *theirString = myString;

/* All pointers will be nil at this time */ ;

self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen]bounds]];

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}

 

 

在 ARC下的这种置零弱关联zeroing weak referencing),是一神奇的方式解开发不知他象在什么时放的问题。而且弱关联也使得象能所指向的象被放后被置nil。这种释放也使得象相关联指向的象都被置nil。
unsafe_unretained型如的名字所含的那,是是的不安全。不安全的原因在于unsafe_unretained型的量所指向的象一旦被放,那么该变量不被置nil指向一未知的存。操作这样量可能会导致程序crash。了防止这样的情况发生,建议将员声明成弱关联类型(即weak型),weak或者内联型的__weak
下面是弱关联例子,改string2weak替代strong

#import <UIKit/UIKit.h>

@interface Moving_from_Manual_Reference_Counting_to_ARCAppDelegate :UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, strong) NSString *string1;

@property (nonatomic, weak)NSString *string2;

@end


程序行,初始化strong型的成string1,赋值给string2。string1赋值为nil,行等待,等待是必的。如果在赋值string1nil立即string2的果的你将会看到错误而不是nil。所以,如果了确保程序的runloop已完全的除了无效的象,建等到程序被切入后台的string2的。一旦程序切入后台,就可以确定程序的runloop已完全除了存中的无效象,我看到的将会如下:

- (BOOL) application:(UIApplication*)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

self.string1 = [[NSString alloc] initWithUTF8String:"String1"]; 

self.string2 = self.string1;

self.string1 = nil;

/* All pointers will be nil at this time */

self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen]bounds]];

self.window.backgroundColor = [UIColor whiteColor]; 

[self.window makeKeyAndVisible];

return YES;

}

- (void)applicationDidEnterBackground:(UIApplication *)application

{

NSLog(@"String 2 = %@", self.string2);

}


程序,等待1、2秒,然后按下home键将程序切入后台,你将会看到控制台果:

String 2 = (null)
简单的例子,明了ARC的弱关联机制(weak)。下面来研unsafe_unretained型的危性,依是上面的代,如我之前strongweak一string2成型由weakunsafe_unretained

#import <UIKit/UIKit.h>

@interface Moving_from_Manual_Reference_Counting_to_ARCAppDelegate :UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, strong) NSString *string1; 

@property (nonatomic, unsafe_unretained) NSString *string2;

@end


如之前一样运行我的程序,把程序切入后台后,你会发现程序crash。意味着程序切入后台后,我尝试输出一string2指向的无效存地址。string2型被unsaf_unretained,它并不知道所指向的(string1)已赋值为nil放。
了添加提到的些新的型,我可以使用__autoreleasing关键字。这个关键字用关联方法传递理。例如,如果一方法需要error或者NSError传递给调用者,用者方法将会返回一未初始化的NSError例到这个方法。意味用者不会真正的分配error,而需要我的方法去做。到目的,指定 error 参数需要在其中合适的时间被自动释放:

- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError

{

NSArray *objects = [[NSArrayalloc] initWithObjects:@"A simple error", nil];

NSArray *keys = [[NSArray alloc]initWithObjects:NSLocalizedDescriptionKey, nil];

NSDictionary *errorDictionary = [[NSDictionary alloc]initWithObjects:objects forKeys:keys];

*paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1userInfo:errorDictionary];

}

- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

NSError *error = nil; [self generateErrorInVariable:&error];

NSLog(@"Error = %@", error);

self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen]bounds]];

self.window.backgroundColor = [UIColor whiteColor]; [self.windowmakeKeyAndVisible]; return YES;

}


这个例子中, application:didFinishLaunchingWithOptions: 方法有分配一个实NSError;用generateErrorInVariable方法来实现。但是必须让编译器知道这个error象的存在。建的被编译器所提及的、含有error参数generateErrorInVariable方法,如果不再使用的话将会被被自动释放。

你可能感兴趣的:(reference)