“未声明的变量”编译到 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' 未声明(在此函数中首次使用)
我已经尝试过这样做:
- 注释这行代码,但随后它在另一个类中给了我一个错误以同样的方式使用基类中的变量(它一次只返回一个错误),因此它似乎不是视图或控制器类中的特定错误,因为该错误发生在具有不同类型的其他类中,例如作为
UIView
和NSObject
类型 - 更改目标编译器配置,例如:架构(全部),基础sdk(全部4.0以上)没有改变任何东西
似乎解决了问题,但不完全
- 创建
_vwHeader
的属性并通过self._vwHeader
或super._vwHeader
访问它似乎可行,但必须仅为了访问变量而创建属性并不让我感到舒服,特别是因为我必须对项目中相同情况下的所有变量执行此操作。 - 更改了 C/C++ 编译器版本:使用
Apple LLVM Compiler 2.1
可以使编译错误消失,但会因项目中使用的其他库而出现一系列其他问题。因此,这不是一个确定的解决方案,但可能是问题所在的线索。
编辑:
我尝试创建另一个不是指针的变量,一个 BOOL
而不是UIView *
然后在继承的类中使用它:问题也会发生
编辑(2):
我的任何类中都没有任何属性,但仍然收到错误。 我刚刚添加了测试海豚的属性,以查看父类中的属性是否导致相同的行为,显然事实并非如此。 同样奇怪的是,当我在变量中收到错误时,我检查了我的智能感知,它发现了它......
I have an custom UIVIewController that is the base class for other controllers and has an instance of a custom UIView variable that is accessed by inherited the classes.
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
The problem is that when I am running it on the simulator everything works perfectly fine, but when I change to the device I have an error on the [_vwHeader setHidden:NO];
line which says: '_vwHeader' undeclared (first use in this function)
I already tried to do:
- Comment this line of code, but then it gives me an error in another class using a variable from the base class the same way (It only returns one error at a time), so it seems that it is not an specific error in the view or the controller class as the error occurs in other clases with different types, such as
UIView
andNSObject
types - Change target compiler configuration, such as: architectures (all of them), base sdk (all above 4.0) didn't change anything
What seem to solve the problem, but not completely
- Creating a property for
_vwHeader
and accessing it byself._vwHeader
orsuper._vwHeader
seems to work, but having to create a property just to access a variable does not make me confortable, specially because I would have to do it for all variables in the same situation inside my project. - changed C/C++ compiler version: using
Apple LLVM Compiler 2.1
makes the compilation error goes away, but gives a bunch of other problems with other libraries being used in the project. So, it is not a definitive solution, but might be a clue of what the problem is.
EDIT:
I tried to create another variable that is not a pointer, a BOOL
instead of the UIView *
and then used it in the inherited class: the problem also occurs
EDIT (2):
I have no properties whatsoever in any of my classes and I still get the error.
I just added the properties for test porpouses, to see if a property in a parent class caused the same behaviour, and apparently it doesn't.
Something that is also weird is that when I get the error in the variable, I checked with my intellisense and it finds it...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
当您为目标和模拟进行编译时,数据成员可能是受保护的或私有的。可能目标默认情况下是私有的,这似乎导致了问题。尝试使用
@private
和@protected
关键字。但是,我强烈建议您甚至在超类/子类之间也使用属性。结构复杂,调试起来有点困难。设置属性将通过 getter/setter 方法转移对数据的访问(@synthesize 上的断点也可以),您将能够在调用堆栈中看到谁正在访问什么。
特别是,语法
@synthesize propertyName = prefixDataNameSufix;
允许您轻松调整类界面风格,而无需修改您的编码习惯。It is possible that when you compile for target and for simulation the data members are either protected or private. Probably for target are private by default and this seems to cause the problem. Try out playing with the
@private
and@protected
keywords.However, I strongly suggest that you use properties even between your super/sub-classes. Having a complex structure is a bit hard to debug. Setting up a property will transfer the access to the data through the getter/setter methods (a breakpoint on
@synthesize
also works) and you will be able to see in the call stack who is accessing what.Especially, the syntax
@synthesize propertyName = prefixDataNameSufix;
allows you to easily adjust your class interface style without having to modify your coding habits.我遇到了完全相同的问题,事实证明我没有删除子类中未使用的 iVar/属性。我们称之为
会话
。我从 iVar 中删除了_session
,但我忘记从属性中删除它,然后在 .m 文件中我有这个synthesize session = _session
。一旦我将它们全部删除,我就可以毫无问题地为 iOS 设备进行编译。如果您认为您的超类没问题,请查看您的子类,检查您的 iVar 和属性并在 .m 文件中综合部分
I had the exact same problem and it turns out that I did not remove an unused iVar/property in the SUBCLASS. Let's call it
session
. I removed_session
from the iVar but I forgot to remove it from the properties, then in the .m file I had thissynthesize session = _session
. Once I removed them all, I can compile for iOS device without problems.If you think your superclass is fine, look into your subclass, check your iVars and properties and synthesize section in the .m file
我遇到了这个问题。
就我而言,我依赖于属性的 ivar 合成。也就是说,我没有声明 UITextView *textView_,但我声明了 @synthesize textView = textView_;
这在我的 iOS 模拟器上构建得很好。但是,无论我使用 llvm 还是 gcc,我的 iOS 设备构建都会失败。
当我将声明添加回我的界面时:
一切正常!
I had this exact problem.
In my case, I was relying on ivar synthesis of a property. That is, I did NOT declare UITextView *textView_, but I did @synthesize textView = textView_;
This builds fine on my iOS Simulator. However, my iOS device build fails, regardless of whether I use llvm or gcc.
When I add the declaration back to my interface:
Everything works fine!
请参阅上面 tc 的答案。这是 sdk 4.2 附带的编译器中的一个错误。
具体来说,我看到了同样的错误,如果在同一台机器上安装了 sdk 4.2 和 sdk 4.3,错误就会消失(即使我编译 4.2)。
See the answer from tc above. This is a bug in the compiler shipped with sdk 4.2.
Specifically I have seen the same error and if on the same machine I have sdk 4.2 and sdk 4.3 installed the error disappears (even if I compile for 4.2).
如果有人在将工具和设备升级到 iOS10 后遇到此问题,我发现问题是在 .h 文件中将它们声明为弱的、非原子的。我以前从未遇到过这种情况,但从属性声明中删除(弱,非原子)后,一切又恢复正常了。
If anyone is having this issue after upgrading their tools and devices to iOS10, I had it and found that declaring them as weak, nonatomic in the .h file was the issue. I had never encountered this when doing so before but after removing (weak, nonatomic) from the property declaration, everything worked fine again.
为了引用除
self
之外的任何对象(包括super
)中的实例变量,必须使用结构指针运算符 (->
)。实例变量的默认范围是受保护的,这意味着它只能在定义它的类或该类的子类中访问。由于CustomViewController
是BaseViewController
的子类,因此此范围足以使用self->_vwHeader
访问变量,但如果第二个类您如果您尝试从不是子类执行此操作,您还需要将范围更改为@public
或@package
。总之,将方法调用更改为:
它应该适用于基本视图控制器的任何子类。
In order to refer to an instance variable within any object other than
self
, includingsuper
, you must use the structure pointer operator (->
). The default scope of an instance variable is protected, which means it can only be accessed within the class it is defined in or a subclass of that class. SinceCustomViewController
is a subclass ofBaseViewController
, this scope is sufficient to access the variable usingself->_vwHeader
, but if the second class you were trying to do this from is not a subclass you will also need to change the scope to either@public
or@package
.In summary, change your method call to:
and it should work for any subclasses of the base view controller.
进行清理并构建,并确保您没有在构建设置中指定特定的框架搜索路径。如果将其留空,您应该获得正确的库。
好吧,我不知道,应该可以。
BaseViewController.h
BaseViewController.m
CustomViewController.m
@end
Do a clean and build, and also make sure you are not specifying a specific framework search path in the build settings. If you leave it empty you should get the correct libraries.
well I don't know, should work.
BaseViewController.h
BaseViewController.m
CustomViewController.m
@end
我遇到了和你类似的问题。就我而言,原因是(奇怪的是!)子类中属性的错误合成。
示例:
您有以下声明
在子类的 .h 文件中,当您以错误的方式合成属性时,
不是
:编译器不会抱怨错误的合成(属性甚至可以正常工作!),而 奇怪地,而是引发错误,当我尝试访问基类中声明的受保护字段时。
详细说明
这是我的代码的样子
我有基类(摘录):
并且我有它的子类(摘录):
并且在 LocationModalController.m 中我有以下错误声明:
尝试访问 LocationModalController 中的 _dataContext 产生了 _dataContext 的错误未声明。
将属性的合成更改为:
神奇地解决了问题!
问候
I faced similar problem as you. In my case the reason was (strangely!) wrong synthesization of properties in subclass.
Example:
In .h file of subclass you have following declaration
while in you synthesize the property in the wrong way:
instead of
Strangely, the compiler does not complain about the wrong synthesization (the properties even work fine!), but raises an error, when I try to access protected fields declared in base class.
Detailed explanation
Here is what my code look like
I have base class (excerpt):
And I have subclass of it (excerpt):
And in the LocationModalController.m I have following wrong declarations:
Trying to access _dataContext in LocationModalController produced the error that _dataContext is undeclared.
Changing the synthesization of properties to:
MAGICALLY SOLVES THE PROBLEM!
Regards
我只是偶然发现了您的方法声明
在视图中,您可以信赖的第一点是在调用 -(void)viewDidLoad 之后,一切都已完全初始化。也许您的代码可以在模拟器上运行,因为您的 Mac 速度足以解决此速度问题 - 但您的移动设备却不能。
也许可以尝试以下编码:
您的 BaseViewController.h 文件:
您的 BaseViewController.m 文件:
您的 CustomViewController.h 文件:
您的 CustomViewController。 m 文件:
现在您的 CustomViewController 可以依赖于 BaseViewController 中的每个实例变量都已正确实例化。
I just stumble upon your method declaration
In a view the first point you can rely that everything is fully initialized is after -(void)viewDidLoad was called. Maybe your code works on the simulator because your Mac is fast enough to cope this speed issue - but your mobile device isn't.
Maybe try this coding:
Your BaseViewController.h file:
Your BaseViewController.m file:
Your CustomViewController.h file:
Your CustomViewController.m file:
Now your CustomViewController can rely on every instance variable in BaseViewController is correctly instantiated.
该错误表明 _vwHeader 未声明。
因此尝试修改以下代码:
CustomViewController.m
The error says that _vwHeader undeclared.
So try by modifying the code in:
CustomViewController.m