编译到iOS设备时出现“可变未声明”错误,但不适用于模拟器

时间:2011-05-18 16:06:12

标签: iphone objective-c ios xcode4 compiler-errors

我有一个自定义的UIVIewController,它是其他控制器的基类,并且有一个自定义UIView变量的实例,可以通过继承类来访问它。

BaseViewController.h

@interface BaseViewController : UIViewController {
    UIView *_vwHeader;
}

@end

BaseViewController.m

#import "BaseViewController.h"
@implementation BaseViewController

-(void)loadView {

    [super loadView];

    _vwHeader = [[UIView alloc] init];
}

@end

CustomViewController.h

#import "BaseViewController.h"
@interface CustomViewController : BaseViewController

@end

CustomViewController.m

#import "CustomViewController.h"
@implementation CustomViewController

- (void)loadView
{
    [super loadView];

    [_vwHeader setHidden:NO];
}

@end

问题在于,当我在模拟器上运行它时,一切都运行得很好,但是当我更改到设备时,我在[_vwHeader setHidden:NO];行上出现了错误:'_vwHeader' undeclared (first use in this function)

我已经尝试过:

  • 注释这行代码,但是它在另一个类中使用基类中的变量以相同的方式给出了一个错误(它一次只返回一个错误),所以它似乎不是特定的错误在视图或控制器类中,因为错误发生在具有不同类型的其他clases中,例如UIViewNSObject类型
  • 更改目标编译器配置,例如:架构(所有这些),基本sdk(均高于4.0)没有改变任何内容

什么似乎可以解决问题,但不完全

  • _vwHeader创建属性并通过self._vwHeadersuper._vwHeader访问它似乎有效,但必须创建一个属性才能访问变量并不会让我感到舒适,特别是因为我必须为我项目中相同情况下的所有变量执行此操作。
  • 更改了C / C ++编译器版本:使用Apple LLVM Compiler 2.1会导致编译错误消失,但是在项目中使用的其他库也存在许多其他问题。因此,它不是一个明确的解决方案,但可能是问题所在的线索。

编辑:

我尝试创建另一个不是指针的变量,BOOL而不是UIView *,然后在继承的类中使用它:问题也出现了

编辑(2):

我的任何课程都没有任何属性,但我仍然得到错误。 我刚刚添加了测试porpouses的属性,以查看父类中的属性是否导致相同的行为,显然它没有。 一些奇怪的事情是,当我在变量中得到错误时,我检查了我的intellisense并且找到了它...

10 个答案:

答案 0 :(得分:8)

为了引用self以外的任何对象(包括super)中的实例变量,必须使用结构指针运算符(->)。实例变量的默认范围是受保护的,这意味着它只能在其定义的类或该类的子类中访问。由于CustomViewControllerBaseViewController的子类,因此该范围足以使用self->_vwHeader访问变量,但如果您尝试执行此操作的第二个类不是子类,那么您也将需要将范围更改为@public@package

总之,将方法调用更改为:

[self->_vwHeader setHidden:NO];

它应该适用于基本视图控制器的任何子类。

答案 1 :(得分:2)

执行清理和构建,并确保未在构建设置中指定特定的框架搜索路径。如果你把它留空,你应该得到正确的库。 我不知道,应该工作。

BaseViewController.h

@interface BaseViewController : UIViewController {
    UIView *_vwHeader;
}
@property(nonatomic,retain)UIView *_vwHeader;
@end

BaseViewController.m

@synthesize _vwHeader;

CustomViewController.m

#import "CustomViewController.h"
@implementation CustomViewController

- (void)loadView
{
    [super loadView];

    [self._vwHeader setHidden:NO];
}

@end

答案 2 :(得分:2)

我遇到了与你类似的问题。在我的情况下,原因是(奇怪的是)在子类中错误地合成属性。

示例:

在子类的.h文件中,您有以下声明

BOOL _flag;
...
@property (nonatomic, assign) BOOL flag;

在你以错误的方式合成属性时:

@synthesize flag;

而不是

@synthesize flag = _flag;

奇怪的是,编译器不会抱怨错误的合成(属性甚至可以正常工作!),但是当我尝试访问基类中声明的受保护字段时会引发错误。


详细解释

这是我的代码看起来像

我有基类(摘录):

@interface BaseEditionModalController : NSObject 
{
    DataContext *_dataContext;
}

我有它的子类(摘录):

@interface LocationModalController : BaseEditionModalController
{
    MCLocation *_readLocation;

    LocationCommModel *_oldLocationCommModel;   
}

//This is MCLocation for reading only - from the main application context
@property (nonatomic, retain) MCLocation *readLocation;

@property (nonatomic, retain) LocationCommModel *oldLocationCommModel;

@end

在LocationModalController.m中,我有以下错误的声明:

@implementation LocationModalController

@synthesize readLocation;
@synthesize oldLocationCommModel;

尝试访问LocationModalController中的_dataContext会产生_dataContext未声明的错误。

将属性的合成更改为:

@implementation LocationModalController

@synthesize readLocation = _readLocation;
@synthesize oldLocationCommModel = _oldLocationCommModel;

神奇地解决问题!

此致

答案 3 :(得分:1)

我只是偶然发现你的方法声明

-(void)loadView { ... }

在视图中,您可以依赖于所有内容完全初始化的第一点是 - (void)viewDidLoad被调用。也许你的代码在模拟器上工作,因为你的Mac足够快以应对这个速度问题 - 但你的移动设备不是。

也许试试这个编码:

您的BaseViewController.h文件:

@interface BaseViewController : UIViewController {
    UIView *_vwHeader;
}
@end

您的BaseViewController.m文件:

#import "BaseViewController.h"
@implementation BaseViewController

-(void)viewDidLoad {
    [super viewDidLoad];
    _vwHeader = [[UIView alloc] init];
}

您的CustomViewController.h文件:

@interface CustomViewController : BaseViewController {
}
@end

您的CustomViewController.m文件:

#import "CustomViewController.h"

-(void)viewDidLoad {
    [super viewDidLoad];
    [_vwHeader setHidden:NO];
}

现在你的CustomViewController可以依赖于BaseViewController中的每个实例变量都被正确实例化了。

答案 4 :(得分:1)

错误说_vwHeader未声明。 因此,请尝试修改以下代码:

CustomViewController.m

    #import "CustomViewController.h"
    @implementation CustomViewController

    - (void)loadView
    {
        [super loadView];
        if(!_vwHeader)
        {
           _vwHeader = [[UIView alloc]init];
        }
        [_vwHeader setHidden:NO];
    }

    @end

答案 5 :(得分:1)

编译目标和模拟时,数据成员可能是受保护的,也可能是私有的。默认情况下,目标可能是私有的,这似乎会导致问题。尝试使用@private@protected关键字进行游戏。

但是,我强烈建议您甚至在超级/子类之间使用属性。具有复杂的结构有点难以调试。设置属性将通过getter / setter方法传递对数据的访问(@synthesize上的断点也有效),您将能够在调用堆栈中看到正在访问的内容。

特别是,语法@synthesize propertyName = prefixDataNameSufix;可让您轻松调整类界面风格,而无需修改编码习惯。

答案 6 :(得分:0)

我遇到了完全相同的问题,结果发现我没有删除SUBCLASS中未使用的iVar /属性。我们称之为session。我从iVar中删除了_session,但我忘记将其从属性中删除,然后在.m文件中我有synthesize session = _session。一旦我将它们全部删除,我就可以毫无问题地为iOS设备编译。

如果您认为您的超类很好,请查看您的子类,检查您的iVars和属性并合成.m文件中的部分

答案 7 :(得分:0)

我遇到了这个问题。

在我的情况下,我依靠ivar合成一个属性。也就是说,我没有声明 UITextView * textView _ ,但我做了 @synthesize textView = textView _;

这在我的iOS模拟器上构建得很好。但是,无论我使用的是llvm还是gcc,我的iOS设备都会失败。

当我将声明添加回我的界面时:

@interface MyTableViewController : BaseTableViewController {
    @private
    UITextView *textView_; // this line is important!
}

一切正常!

答案 8 :(得分:0)

请参阅上述tc的答案。这是sdk 4.2附带的编译器中的一个错误。 具体来说,我已经看到了相同的错误,如果在同一台机器上我安装了sdk 4.2和sdk 4.3错误消失了(即使我编译为4.2)。

答案 9 :(得分:0)

如果在将他们的工具和设备升级到iOS10之后有任何人遇到此问题,我就会发现它并发现在.h文件中声明它们是弱的非原子问题。我之前从未遇到过这种情况,但是在从属性声明中删除(弱,非原子)后,一切都运行良好。