我有一个自定义的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)
我已经尝试过:
UIView
和NSObject
类型什么似乎可以解决问题,但不完全
_vwHeader
创建属性并通过self._vwHeader
或super._vwHeader
访问它似乎有效,但必须创建一个属性才能访问变量并不会让我感到舒适,特别是因为我必须为我项目中相同情况下的所有变量执行此操作。Apple LLVM Compiler 2.1
会导致编译错误消失,但是在项目中使用的其他库也存在许多其他问题。因此,它不是一个明确的解决方案,但可能是问题所在的线索。 编辑:
我尝试创建另一个不是指针的变量,BOOL
而不是UIView *
,然后在继承的类中使用它:问题也出现了
编辑(2):
我的任何课程都没有任何属性,但我仍然得到错误。 我刚刚添加了测试porpouses的属性,以查看父类中的属性是否导致相同的行为,显然它没有。 一些奇怪的事情是,当我在变量中得到错误时,我检查了我的intellisense并且找到了它...
答案 0 :(得分:8)
为了引用self
以外的任何对象(包括super
)中的实例变量,必须使用结构指针运算符(->
)。实例变量的默认范围是受保护的,这意味着它只能在其定义的类或该类的子类中访问。由于CustomViewController
是BaseViewController
的子类,因此该范围足以使用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文件中声明它们是弱的非原子问题。我之前从未遇到过这种情况,但是在从属性声明中删除(弱,非原子)后,一切都运行良好。