我知道HIG(这非常方便!),但是在编写Objective-C时使用了什么编程实践,更具体地说,在使用Cocoa(或CocoaTouch)时.
我已经知道dealloc你在做([object release];但在viewDidUnloadUIViewController子类中)你做了self.object = nil.真正的区别是因为self.object = nil(我们假设对象是(nonatomic, retain)属性)保留nil(什么也不做)然后释放旧值然后引用计数为0对吗?
我现在从几个来源(stackoverflow.com,cocoa-dev,文档,博客等)中听到,在init和dealloc方法中使用访问器和设置(foo,setFoo :)是"错误的".据我所知,如果你这样做,很可能会混淆其他正在观察财产的物体.(这里给出一个简单的例子)
但是,由于以下原因,我不得不说我不同意这种做法:
新的Objective-C运行时(iPhone上的那个和10.5中的64位运行时)允许您在不声明相应的ivar的情况下声明属性.例如,以下类将在10.5或iPhone(设备,而不是模拟器)上编译得很好:
@interface Foo : NSObject { }
@property (retain) id someObject;
@end
@implementation Foo
@synthesize someObject;
@end
Run Code Online (Sandbox Code Playgroud)
理解上面是一个完全有效的Objective-C类,假设我决定编写一个初始化程序,并且出于内存管理的目的,使用dealloc方法(因为在iPhone上没有GC).我读过有关初始化器和释放器的所有内容都会让我编写以下两种方法:
- (id) init {
if (self = [super init]) {
//initialize the value of someObject to nil
[self setSomeObject:nil];
}
return self;
}
- (void) dealloc {
//setting someObject to nil will release the previous value
[self setSomeObject:nil];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
但是,根据文件和流行的观点,这是"错误的".所以我的问题是这样的:
如果其中任何一个的答案是"你不能",那么在init和dealloc方法中使用访问器怎么可能不好?
为内存管理带来的好处,为私有变量创建@properties是不是很糟糕?
对于许多私有变量,让公众面对@properties似乎是混乱和错误的.
(主要是,我在低内存条件下使用相应的"事件"方法释放私人ivars.)
示例: 我通常这样做是为了发布一个私有的ivar:
[name release]; name = nil;
Run Code Online (Sandbox Code Playgroud)
但是使用@properties,我可以这样做:
self.name = nil;
Run Code Online (Sandbox Code Playgroud)
稍后在我的代码中,将执行此操作,因此需要设置为nil:
if( !name)
name = [[NSString alloc] initWithFormat:@"Hi %@",inputName];
Run Code Online (Sandbox Code Playgroud) 您可以在objective-c中声明一个方法,并基本上将每个参数命名为两次.
我觉得这很强大,但我还不确定如何使用它......
当John Greets Kelly:
[ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ;
关于它的一些东西不能自然地阅读.我不确定这是一个经验丰富的Objective-c程序员是如何写出"消息"的.
有人可以解释每个参数的两个名称的原因,并可能是一个更有用的例子,说明如何有效地使用它来在程序中加入意义?
还有什么困扰我,这是第一个参数的名称基本上与' 消息 ' 的名称相同.你如何通过编写有意义且易于理解的方法/'消息名称'来解决这个问题?
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
}
-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;
@end
@implementation Person
-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;
{
printf( "%s says %s to %s\n", from, greeting, to ) ;
}
@end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Person * p = [ Person … 在某个地方,我正在阅读 - 关于低记忆警告和放弃一个不可见的视图及其所有的子视图(=我觉得整个笔尖),你应该这样做:
-(void)dealloc {
[anView release], anView = nil;
[someImageView release], someImageView = nil;
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
而不是
-(void)dealloc {
[anView release];
[someImageView release];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
在我调用release之后,将这些指针接口为nil(="no object")的原因是什么?让我猜一下:其他一些方法可能因为某种原因而得到了视图(任何人可以在何时发生这种情况?),然后发生didReceiveMemoryWarning事件,并释放一个当前不可见的整个笔尖+视图(即在multiview-app中).一旦用户想再次看到该视图,您将再次快速加载笔尖然后:它加载所有视图,连接插座,然后砰!你的另一个保留视图现在已经挂起,没有任何指针在内存块中的某个地方孤独,导致内存泄漏,直到你的应用程序崩溃.
正确错误?
从Apple有关内存管理的文档:
您不应该使用访问器方法来设置实例变量的唯一地方是init方法和dealloc.要使用表示零的数字对象初始化计数器对象,可以按如下方式实现init方法:
要允许使用非零计数初始化计数器,您可以实现initWithCount:方法,如下所示:
- initWithCount:(NSNumber *)startingCount {
self = [super init];
if (self) {
count = [startingCount copy];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
为什么不 ?
我知道如果任何其他对象正在观察属性的变化,那么在dealloc中使用setter会产生问题.但为什么我们不应该在初始化器中使用它们?
@interface MainView : UIView {
NSMutableString *mutableString;
}
@property (nonatomic, retain) NSMutableString *mutableString;
@end
@implementation MainView
@synthesize mutableString;
-(void) InitFunc {
self.mutableString=[[NSMutableString alloc] init];
}
-(void) AppendFunc:(*NString) alpha {
[self.mutableString stringByAppendingString:@"hello"];
NSLog(@"the appended String is: %@",self.mutableString);
int len=[self.mutableString length];
}
Run Code Online (Sandbox Code Playgroud)
嘿大家,
我只是想知道我在哪里做错了??? .我试过这段代码但是"mutableString"没有附加任何值(因为"len"的值为'0'且NSLog没有为"mutableString"打印任何值),尽管我在网上搜索了解决方案,人们在同样的时尚,我不知道为什么我的代码不工作.
提前致谢
MGD
.h
@ interface MyClass : NSObject {
UILabel *mTextLabel;
}
@property (nonatomic, retain) UILabel *mTextLabel;
Run Code Online (Sandbox Code Playgroud)
并在MyClass.m中声明@synthesize mTextLabel ;
并释放这样的对象.
[self setMTextLabel:nil];
[mTextLabel release];
NSLog (@"%d",[mTextLabel retainCount]);
Run Code Online (Sandbox Code Playgroud)
结果为0.我没有发现任何错误或中断.
但.当我像这样发布mTextLabel时.我刚刚得到了EXC_BAD_ACCESS
[mTextLabel release];
[self setMTextLabel:nil];
Run Code Online (Sandbox Code Playgroud)
我不明白为什么会这样.Plz帮助我.
我对属性的两个假设是否正确?
@interface Foo : NSObject {
NSDate *Created;
}
@property (nonatomic, retain) NSDate *Created;
@end
@implementation Foo
@synthesize Created;
- (id) init {
if(self = [super init])
{
Created = [NSDate date]; //this will not call the setter and instead just access the variable directly, which means it will not automatically get retained for me.
self.Created = [NSDate date]; // this will call the setter, which will retain the variable automatically for me.
}
return self;
}
- (void)dealloc { …Run Code Online (Sandbox Code Playgroud) objective-c ×9
properties ×6
iphone ×4
cocoa-touch ×3
release ×2
accessor ×1
cocoa ×1
dealloc ×1
ios ×1
nsstring ×1
null ×1
object ×1
uikit ×1