strong:这种类型的对象在run-time的时候自动增加引用计数,并在它范围结束之前有效,之后就会被自动释放,熟悉Objective-C传统的内存管理办法的话,这个关键字和retain关键字很相似。
weak:这是 “归零弱引用 ”。如果变量使用这个关键字定义,当对象(变量指向的内存)被销毁了,这个变量会被设置为nil。例如:你有一个strong的string属性和一个weak的string属性,并将weak属性的值设置为strongoing属性的值,当strong属性被销毁了,那么weak属性就会被设置为nil。unsafe_unretained:简单的将一个变量指向另一个变量。设置对象的新数值,不会增加它的引用计数,它只是简单的为变量分配了一个对象而。
默认,所有的局部变量是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, strong) NSString *string2; @end
#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.window makeKeyAndVisible]; return YES; } 输出为:String 2 = String 1
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ /* All local variables are by default strong so just emphasis that. We really don't have to mention __strong for the first variable but to make it clear, 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; }
#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属性,然后将string1分配给string2.然后我们将string1的值设为nil。然后等待,这绝对是至关重要的。runloop除去所有无效的对象。为了实现这个目标,我们在应用程序将要进入后台的时候,我们将打印string2的值。(这是在用户将另一个应用程序移到前台时,你的应用程序进入后台)。一旦程序在后台运行,我们知道runloop已经除去了内存中所有无效对象,并且我们得到的结果将是正确的:
/* 3 */ - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.string1 = [[NSString alloc] initWithUTF8String:"String 1"]; 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);
String 2 = (null)
#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
- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError{ //the caller method,声明参数的类型是自动释放的类型 NSArray *objects = [[NSArray alloc] 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:1 userInfo: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.window makeKeyAndVisible]; return YES; }