问题 编译到iOS设备时出现“可变未声明”错误,但不适用于模拟器
我有一个自定义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中,例如
UIView
和 NSObject
类型
- 更改目标编译器配置,例如:架构(所有这些),基本sdk(都高于4.0)没有改变任何东西
什么似乎解决了这个问题,但并不完全
- 为...创建属性
_vwHeader
并通过访问它 self._vwHeader
要么 super._vwHeader
似乎工作,但必须创建一个属性只是为了访问变量不会让我很舒服,特别是因为我必须在我的项目内的相同情况下为所有变量做这件事。
- 改变了C / C ++编译器版本:使用
Apple LLVM Compiler 2.1
使编译错误消失,但在项目中使用的其他库给出了一堆其他问题。因此,它不是一个明确的解决方案,但可能是问题所在的线索。
编辑:
我试图创建另一个不是指针的变量,a BOOL
而不是 UIView *
然后在继承的类中使用它:问题也会发生
编辑(2):
我的任何课程都没有任何属性,但我仍然得到错误。
我刚刚添加了测试porpouses的属性,以查看父类中的属性是否导致相同的行为,显然它没有。
一些奇怪的事情是,当我在变量中得到错误时,我检查了我的intellisense它发现它...
2423
2018-05-18 16:06
起源
答案:
为了引用除了之外的任何对象中的实例变量 self
, 包含 super
,你必须使用结构指针运算符(->
)。实例变量的默认范围是受保护的,这意味着它只能在其定义的类或该类的子类中访问。以来 CustomViewController
是。的子类 BaseViewController
,此范围足以使用访问变量 self->_vwHeader
,但如果您尝试执行此操作的第二个类不是子类,则还需要将范围更改为 @public
要么 @package
。
总之,将方法调用更改为:
[self->_vwHeader setHidden:NO];
它应该适用于基本视图控制器的任何子类。
8
2018-05-19 04:04
做一个干净的构建,并确保您没有在构建设置中指定特定的框架搜索路径。如果你把它留空,你应该得到正确的库。
我不知道,应该工作。
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];
}
@结束
2
2018-05-18 18:33
我遇到了和你一样的问题。在我的情况下,原因是(奇怪的是)在子类中错误地合成属性。
例:
在子类的.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;
神奇地解决了问题!
问候
2
2018-06-15 14:24
我只是偶然发现你的方法声明
-(void)loadView { ... }
在视图中,您可以依赖于所有内容都已完全初始化的第一点是在调用viewDidLoad之后 - (void)。也许你的代码可以在模拟器上运行,因为你的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中的每个实例变量来正确实例化。
1
2017-07-27 16:10
该错误表明_vwHeader未声明。
因此,请尝试修改以下代码:
CustomViewController.m
#import "CustomViewController.h"
@implementation CustomViewController
- (void)loadView
{
[super loadView];
if(!_vwHeader)
{
_vwHeader = [[UIView alloc]init];
}
[_vwHeader setHidden:NO];
}
@end
1
2017-07-28 04:42
编译目标和模拟时,数据成员可能是受保护的,也可能是私有的。默认情况下,目标可能是私有的,这似乎会导致问题。尝试玩 @private
和 @protected
关键字。
但是,我强烈建议您甚至在超级/子类之间使用属性。具有复杂的结构有点难以调试。设置属性将通过getter / setter方法(断点)传输对数据的访问 @synthesize
也工作)你将能够在调用堆栈中看到谁正在访问什么。
特别是语法 @synthesize propertyName = prefixDataNameSufix;
允许您轻松调整类界面风格,而无需修改编码习惯。
1
2017-07-29 08:05
我有完全相同的问题,事实证明我没有删除SUBCLASS中未使用的iVar /属性。我们称之为 session
。我删除了 _session
从iVar但我忘了从属性中删除它,然后在.m文件中我有这个 synthesize session = _session
。一旦我将它们全部删除,我就可以毫无问题地为iOS设备编译。
如果您认为您的超类很好,请查看您的子类,检查您的iVars和属性并合成.m文件中的部分
0
2017-08-11 03:32
我遇到了这个问题。
在我的情况下,我依靠ivar合成一个属性。也就是说,我没有声明 UITextView * textView_,但我做到了 @synthesize textView = textView_;
这在我的iOS模拟器上构建得很好。但是,无论我使用llvm还是gcc,我的iOS设备构建都会失败。
当我将声明添加回我的界面时:
@interface MyTableViewController : BaseTableViewController {
@private
UITextView *textView_; // this line is important!
}
一切正常!
0
2017-09-15 08:54
请参阅上面的tc的答案。这是sdk 4.2附带的编译器中的一个错误。
具体来说,我已经看到了相同的错误,如果在同一台机器上我安装了sdk 4.2和sdk 4.3错误消失了(即使我编译为4.2)。
0
2018-01-17 10:12
如果在将他们的工具和设备升级到iOS10之后有人遇到这个问题,我就有了它,发现在.h文件中声明它们是弱的,非原子的是问题。我之前从未遇到过这种情况,但是在从属性声明中删除(弱,非原子)之后,一切都运行良好。
0
2017-10-10 14:16