【问题标题】:Obj-C properties, scopes, and helper classesObj-C 属性、范围和辅助类
【发布时间】:2011-12-09 18:17:31
【问题描述】:

我一直在尝试了解 iOS 系统的一些细微差别以及我不清楚的一项。我正在构建一个类来封装访问日历的方法,其中包括创建事件、事件存储单例和异步获取操作。

类变量和实例变量混合在一起,但我很难让它发挥作用。

我的问题是这个。

让我们看看这个项目。

http://developer.apple.com/library/ios/#samplecode/SimpleDrillDown

Play 类封装了有关戏剧的信息。

@interface Play : NSObject
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSArray *characters;
@property (nonatomic, strong) NSString *genre;
@property (nonatomic, strong) NSDate *date; 
@end

#import "Play.h"
@implementation Play
@synthesize title, characters, genre, date;
@end

因为synthesize,所以没有dealloc方法,如果我理解正确的话。

现在,没有定义其他方法。

在示例项目的详细信息控制器中,对象根本没有初始化,但属性可以通过引用访问,这让我很困惑。如果我尝试在 Play 中编写方法,则方法无法更改属性中的值。例如,如果您尝试将 Data Controller 类与 Play 类合并,我注意到方法无法从属性中设置和获取值。

例如,如果我添加到 Play 类中:

(void)createSamplePlay
{
    self.title = @"Play 1";
    self.characters = [NSArray arrayWithObject:[NSString stringWithFormat:@"Character 1"]];
    self.genre = @"Genre 1";
    self.date = [NSDate date];
}

然后我调用 Details Controller 中的方法,实际上没有任何改变。如果我将方法移动到详细信息控制器内部,声明一个静态类型属性Play *play,然后调用方法[self createSamplePlay];并将self更改为play,那么这些方法当然有效。

我不知道我的理解是否存在根本性的误解,或者只是上面的代码是编写的,而我在实际和更长的项目中遇到了错误。

与此同时,我将继续阅读来自 developer.apple.com 的 Obj-C PDF。

编辑:

抱歉,这是我最终意图的一个不好的例子。

假设我想编写一个执行此操作的方法:

-(void)fillInMissingGenre
{
    if([self.title caseInsensitiveCompare:@"Romeo and Juliet"] == 0){
        self.genre = @"Tragedy";
    }
}

在示例代码中,PlayData Controller 实例化,返回给 Root Controller,然后传递给 Detail Controller ,通过 Detail Controller 的 Play 属性。 Root 和 Detail 都应该能够调用 Play 的 方法,除非前面的实体之一决定取消引用该对象。

我开始怀疑这是我的问题的原因,因为有时Play 对象对所有内容都返回 nil,然后有时我得到一个 Exec_Bad_Access。如果我只学会使用那个调试器就好了。 . .

【问题讨论】:

    标签: iphone objective-c properties helper


    【解决方案1】:

    因为synthesize,所以没有dealloc方法,如果我理解正确的话。

    错了。没有dealloc,因为此代码是为 ARC(自动引用计数)编写的。与@synthesize无关。

    除此之外,我认为您忽略了类和对象之间的区别。属性是在Play class 上定义的,但要实际使用它们(存储数据),您需要创建一个 objectinstance 类。你这样做:

    Play *myPlay = [[Play alloc] init];
    

    现在您可以使用 object myPlay(或更准确地说,myPlay 是一个指向对象的指针)来执行类似 `myPlay.title = @"Play 1";

    如果您不创建实例,它将无法工作:

    Play *myPlayNoInstance;
    myPlayNoInstance.title = @"Play 2"; // doesn't do anything
    

    因为这里,myPlayNoInstance 是一个不指向已分配对象的指针。

    【讨论】:

    • 这可能是我的问题。如果我是上面示例中的详细信息控制器,那么我不应该初始化,也不需要复制,除非我想要一个强引用?
    • 无论如何,您都不应该初始化或制作副本,除非您想制作一个全新的对象。每次创建对象时都必须分配内存。但是,如果您只是想访问该对象(无论是用于编辑、查看等),您只需要创建一个指向它的新指针。
    【解决方案2】:

    如果我正确理解您的意图,createSamplePlay 是一种工厂方法。如果这个假设是正确的,你应该在Play 类中声明它(注意+ - 它是一个类方法的指示符),并像这样重写实现:

    + (id) createSamplePlay
    {
        self = [[Play  alloc] init];
        self.title = @"Play 1";
        self.characters = [NSArray arrayWithObject:[NSString stringWithFormat:@"Character 1"]];
        self.genre = @"Genre 1";
        self.date = [NSDate date];
        return self;
    }
    

    稍后您可以在代码中使用它:

    Play *sample = [Play createSamplePlay];
    

    因为synthesize,所以没有dealloc方法,如果我理解正确的话。

    不,因为自动引用计数,dealloc 不存在(strong 修饰符的存在告诉您您在 ARC 领域)。

    【讨论】:

    • 当我看到没有 dealloc 时,我以为我快疯了。
    • 感谢您的回答,我添加了说明。
    猜你喜欢
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 2018-08-13
    相关资源
    最近更新 更多