2012-03-19 76 views
2

我想弄清楚合成myString到实例变量_myString的目的是什么。iPhone实例变量问题

这样做的目的是什么?我倾向于注意到很多人这样做。

另外我应该释放实例变量并将实例变量设置为零,是否正确。

ViewController.h

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController 
{ 
    NSString *_myString; 
} 

@property (nonatomic, retain) NSString *myString; 

@end 

ViewController.m

#import "ViewController.h" 

@implementation ViewController 

@synthesize myString = _myString; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.myString = [[NSString alloc] initWithFormat:@"Hello"]; 

    _myString = [[NSString alloc] initWithFormat:@"Goodbye"]; 

    NSLog(@"%@\t%@", self.myString, _myString); 
} 

- (void)viewDidUnload 
{ 
    _myString = nil; 
    [super viewDidUnload]; 
} 

- (void)dealloc 
{ 
    [_myString release]; 
    [super dealloc]; 
} 

@end 
+0

就我们的声望而言,你应该知道我们为什么要使用综合......就我的观点而言,综合主要用于我们想要全局使用对象的时候(它也有另一个优点)..因为我知道.. :) – Krunal 2012-03-19 13:58:13

+0

我知道它合成创建一个getter和setter为什么设置它等于实例变量? – Vikings 2012-03-19 14:05:05

+0

有一件事:你不应该在'viewDidUnload'中剔除'_myString',这个方法在'viewControllers'' view''被卸载并且与'myString'(或iVar'_myString')无关时调用。在'viewDidUnload'中,你应该省略掉连接到'.xib'的'IBOutlet'。 – 2012-03-19 14:07:05

回答

3

当您在目标c中合成一个对象类型属性时,编译器将为该实例变量生成两个隐藏方法。因此,当您参考myObject.myString时,不仅会返回_myString的指针,而且会调用生成的- (NSString*) myString方法。同样,如果您将某些内容分配给该属性:myObject.myString = @"foo";它将被编译为[myObject setMyString:@"foo"];

什么是- (NSString*) myString- (void) setMyString:(NSString*) theString取决于您在声明属性时指定的关键字。最常见的是assign简单为您分配给指针:

- (void) setMyString:(NSString*) theString 
{ 
    _myString = theString; 
} 

- (NSString*) myString 
{ 
    return _myString; 
} 

这使得不声明_myString公共变量太大的区别,但它是说,这个变量可以从外部直接访问更明确的方式。

反过来,retain产生类似的setter方法(getter方法是相同的):

- (void) setMyString:(NSString*) theString 
{ 
    [theString retain]; 
    [_myString release]; 
    _myString = theString; 
} 

你可以看到,这需要你传入的属性的对象的内存管理的照顾。换句话说,您可以确定该物品在您的物业拥有它之前不会被释放,因此在您拥有物品时您不必手动使用retain。这使编写管理内存而不泄漏的代码更方便。请注意,在dealloc中,您仍然必须向您的属性应用nil才能释放其存储的最后一个对象。

数据不是来自实例变量,而是来自其他数据源(如数据库)的另一类属性。例如,Core Data的Managed Objects的自动生成的属性就是如此。

最后,你也可以定义你自己的getters和setter。例如一个好主意,写身边的一些常用NSUserDefaults设置的属性包装,这将有利于它的访问:

@interface Bar 

@property (nonatomic, assign) NSString* foo; 

@end 

@implementation Bar 

- (void) setFoo:(NSString *)theFoo 
{ 
    [[NSUserDefaults standardUserDefaults] setObject:theFoo 
               forKey:@"settings.foo"]; 
} 

- (NSString*) foo 
{ 
    return [[NSUserDefaults standardUserDefaults] 
     stringForKey:@"settings.foo"]; 
} 

@end 

myBar.foo = @"foobar"; // automatically persisted between application runs 

阅读这些也:Advanced memory managementDeclared properties in objective C

+0

因此,在我的项目中,我应该使用_myString或self .myString?我猜self.myString。 – Vikings 2012-03-19 15:13:03

+1

是的,除了init和dealloc。这是详细的原因:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW4 – MrTJ 2012-03-19 15:34:55

+0

非常感谢,清除了。 – Vikings 2012-03-19 21:54:14

1

self.myString(技术上[自的myString])的实际访问和设置的ivar通过这样写此对象中的函数_myString这个:

-(NSString *)myString { 
    // code that is automatically generated by the @synthesize statement OR 
    // code that you write which over-rides the generated accessor. 
    // both of which generally return the value stored in _myString 
} 

-(void)setMyString:(NSString *)newString{ 
    // code that generally changes the value of _myString 
} 

使用_myString直接绕过这些func并直接访问伊娃。

0

人们倾向于综合属性来强调前缀变量,而不是在编写其他代码时将两者错误。例如:

// ... do sth 
myString = @"Foo"; 
// ... do sth else ... 
self.myString = @"Bar"; 

第一条指令直接访问变量,第二条指令使用合成的setter。当你合成,而不指向特定的变量,然后为属性为您创建的同名变量:

@synghesize myString; // this creates myString variable for you 

而不是这样做,人们创造下划线前缀变量,以避免错误地直接访问它。当他们这样做时,第一条指令myString = @"Foo"不再编译,这使得当你绕开getter或setter错误时,很容易防止像那些令人讨厌的错误。

至于你的第二个问题,如果可能的话使用ARC。如果没有,你应该先释放变量,然后重置指针。在你提交的代码中,viewDidUnload将比dealloc调用的早,所以你将会有内存泄漏,因为_myString在调用release之前会指向nil。