首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我怎么知道不声明@synthesize是否会导致“使用未声明的标识符”?

我怎么知道不声明@synthesize是否会导致“使用未声明的标识符”?
EN

Stack Overflow用户
提问于 2013-05-07 20:02:13
回答 1查看 362关注 0票数 1

在其中一个任务中,我必须覆盖游戏逻辑的超类的getter方法(因此该方法将获得游戏逻辑的子类,而不是原始的子类)。

CardGameViewController.h:

代码语言:javascript
复制
#import <UIKit/UIKit.h>
#import "Deck.h"
#import "CardGame.h"

@interface CardGameViewController : UIViewController
@property (nonatomic) NSUInteger startingCardCount; // abstract
@property (strong, nonatomic) CardGame *game;

- (Deck *)createDeck; // abstract
- (void)updateCell:(UICollectionViewCell *)cell usingCard:(Card *)Card; // abstract

@end

CardGameViewController.m:

代码语言:javascript
复制
#import "CardGameViewController.h"

...

// no @synthesize here, but works fine.

- (CardGame *)game
{
    if (!_game) _game = [[CardGame alloc] initWithCardCount:self.startingCardCount
                                                 usingDeck:[self createDeck]];
    return _game;
}

...

@end

SetCardGameViewController.m:

代码语言:javascript
复制
...

@interface TSSetCardGameViewController()

@property (strong, nonatomic) CardGame *game;

@end

@implementation TSSetCardGameViewController

@synthesize game = _game; // Compiler *will* complain if this line is commented out.

- (CardGame *)game
{
    if (!_game) _game = [[SetCardGame alloc] initWithCardCount:self.startingCardCount
                                                  usingDeck:[self createDeck]];
    return _game;
}

...

@end

然后我得到了"_game“的”未声明标识符的用法“。所以我宣布

代码语言:javascript
复制
@property (strong, nonatomic) CardGame *game;

但是我得到了相同的错误,所以我使用了"self.game“,这导致了一个糟糕的访问异常。我在Google上找不到任何东西,所以我到处修补,直到我发现这解决了问题:

代码语言:javascript
复制
@synthesize game = _game;

现在,我的问题是为什么。我的理解是,新版本的Xcode会为我进行合成,除非我同时覆盖它的getter和setter。我确实覆盖了getter,但没有覆盖setter,所以从技术上讲,Xcode应该自动包含它。证据是,直到我将CardGameViewController子类化并特别重写了getter方法,Xcode才开始抱怨。(仅供参考,CardGameViewController和它的子类都没有*game的setter方法)

所以我有点困惑。请帮帮我!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-07 23:06:58

这里的问题是您有两个版本的_game。自从引入新的ABI (64位Mac和所有iOS)以来,每个子类都可以创建自己的ivars,而无需遍历其父类的ivars (即使它们的名称相同)。@synthesize创建的ivar是私有的。现在保持这种想法,让我们看看发生了什么:

您可以重写getter。编译器会说:“但是你仍然想让我为你创建一个setter,所以我会创建一个匹配它的ivar。”

  • 在你的子类中,你没有声明新的属性。您可能认为您需要,但它只是来自超类的相同属性;它不是一个新属性。超类中已经有了getter和setter,所以编译器不需要创建ivar。

  • 然后你引用了一个在你的子类中不存在的ivar。它只作为一个私有ivar存在于超类中。编译器看不到这一点(即使可以,也不会让您访问它)。

这个问题的典型解决方案是,只需提供一个名为+gameClass的类方法,并让它返回要实例化的正确类,而不是覆盖-game。(有关此模式的示例,请参阅UIView中的+layerClass。)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16418532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档