【问题标题】:NSString Retain ProblemsNSString 保留问题
【发布时间】:2009-07-25 03:57:29
【问题描述】:

我在保留 NSString 时遇到了一些问题。我的问题是,在第二个函数(runItem)上,它似乎没有注意到 item1 的值。无论我将其设置为什么,它似乎都设置为 nil。我正在为 Cocoa(桌面,与 iPhone)编程,我以前没有遇到过 NSString 的此类问题。我不确定我在做什么来导致它,所以如果有人可以帮助我,我将非常感激!我的 AppController.h 文件中的代码:

@interface AppController : NSObject {
    NSString *item1;
}
@property (retain) NSString *item1;

- (IBAction)runItem:(id)sender;

@end

还有 AppController.m:

@synthesize item1;

- (void)awakeFromNib: {
    NSDictionary *savedFile = [NSDictionary dictionaryWithContentsOfFile:@"Users/me/Desktop/Testing.plist"];
    if (savedFile != nil) {
        item1 = [savedFile objectForKey:@"Item Title"];
        AppController *runFunction = [[AppController alloc] init];
        [runFunction runItem:self];
    }
    else {
        item1 = nil;
    }
}

- (IBAction)runItem:(id)sender 
    NSLog(@"%@", item1);
}

【问题讨论】:

    标签: cocoa memory-management


    【解决方案1】:

    嗯,虽然您在第一个 AppController 对象中设置了 item1(由应用程序创建的对象,因为它与 NIB 文件相关联),但您正在创建一个 second @ 987654323@ 对象(直接通过默认的“init”构造函数),其item1 从未设置。然后你要第二个对象的item1,所以当然是nil

    也许这是因为您认为每当初始化对象时都会调用awakeFromNib?但这完全不是真的。 awakeFromNib 仅在加载 NIB 文件时创建的对象调用。

    【讨论】:

    • newacct:这很有意义。我将其切换为 [self runItem:self],现在效果很好。感谢您的帮助!
    【解决方案2】:

    问题 #1:在您提供的示例中,您有以下内容:

    - (void)awakeFromNib: {
    

    NSNibAwaking 协议仅定义 awakeFromNib非常要注意末尾没有冒号。如果你的代码中的这个方法实际上被调用了,那么它可能是由于一些内部的怪异而不是你应该依赖的东西(除非你可以在某处找到它,而我不能)。我对文档的快速浏览表明 awakeFromNib 是唯一将被调用的选择器。

    问题 #2:

    NSDictionary *savedFile = [NSDictionary dictionaryWithContentsOfFile:@"Users/me/Desktop/Testing.plist"];
    

    我很确定您的真正意思是/Users,而不是Users。这可能意味着savedFile 始终为NULL,因为它从不加载,因此以下if() 检查将始终使用else 条件。

    问题 #3:

    item1 = [savedFile objectForKey:@"Item Title"];
    

    如果您不使用 GC,则此行是一个问题,因为从字典 savedFile 检索到的对象尚未保留。此外,如果item1 包含指向对象的有效指针,则您只是通过直接覆盖它来泄漏它。你的意思可能是self.item1 =

    这一行的第二个问题,与问题行为有关,是不能保证savedFile 字典具有键@"Item Title" 的对象。如果没有,它将返回NULL

    问题 #4:

    item1 = nil;
    

    如果item1 包含指向对象的有效指针,则您只是泄漏了它。你的意思可能是self.item1 = nil;

    【讨论】:

    • johne:我已经纠正了这些问题,这是非常好的建议,以后要记住。
    • @johne 你能解释一下 item1=nil 和 self.item1=nil 之间的区别吗? tnx 我应该总是将 self 用于合成对象吗?
    【解决方案3】:

    你没有保留它,因为你没有通过属性——你直接分配给实例变量。使用self.item1 = [savedFile objectForKey:@"Item Title"] 使用属性的综合设置器设置值,它将保留它。

    此外,对于值符合NSCoding 的属性,您应该使用copy,而不是retain,尤其是当这些值可能是可变的时。字符串就是这样一种情况:你真的不想在别人变异的时候抓住别人的可变字符串。您想制作自己的副本,这样无论其他对象对其字符串做什么,您的字符串的值都保持不变。

    【讨论】:

    • 嗨,彼得:感谢您的建议。我将来肯定会考虑到这一点。但是,对于这个问题,似乎无论我如何保留item1,它仍然不起作用。我将 item1 的所有实例都更改为“self.item1” - 但即使在更改后,它仍然无法正常工作。即使调用了[item1 retain],它仍然拒绝retain。
    【解决方案4】:

    需要更多细节:

    • 你知道 awakeFromNib 被调用了吗?
    • 你知道 savedFile 不是 nil 吗?
    • 您知道 savedFile 中的“项目标题”存在且不为零吗?

    此外,简单地调用item1 = @"something" 不会导致它按照@property 语句中的定义保留,您需要调用self.item1 = @"something" 才能使用合成属性,否则您只是直接设置指针。

    【讨论】:

    • 嗨 Nick:1. 是的,awakeFromNib 被调用了,我再次检查了 NSLog 语句。 2. 我相信我通过运行“if (savedFile != nil)”检查了这一点,但我可能错了。 3. 是的,该值存在于文件中。此外,这对 self.item1 部分很有意义 - 但即使添加了这个,它仍然不起作用。另外,只是为了尝试一下,我打电话给 [item1 retain] 看看它是否会以这种方式工作,但事实并非如此。所以我在想,出于某种原因,不管你怎么称呼它,它根本就不是保留。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多