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

发布于 2024-11-08 06:26:11 字数 1722 浏览 0 评论 0原文

我有一个自定义 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' 未声明(在此函数中首次使用)

我已经尝试过这样做:

  • 注释这行代码,但随后它在另一个类中给了我一个错误以同样的方式使用基类中的变量(它一次只返回一个错误),因此它似乎不是视图或控制器类中的特定错误,因为该错误发生在具有不同类型的其他类中,例如作为 UIViewNSObject 类型
  • 更改目标编译器配置,例如:架构(全部),基础sdk(全部4.0以上)没有改变任何东西

似乎解决了问题,但不完全

  • 创建 _vwHeader 的属性并通过 self._vwHeadersuper._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 and NSObject 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 by self._vwHeader or super._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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

坠似风落 2024-11-15 06:26:12

当您为目标和模拟进行编译时,数据成员可能是受保护的或私有的。可能目标默认情况下是私有的,这似乎导致了问题。尝试使用 @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.

你的笑 2024-11-15 06:26:12

我遇到了完全相同的问题,事实证明我没有删除子类中未使用的 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 this synthesize 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

征棹 2024-11-15 06:26:12

我遇到了这个问题。

就我而言,我依赖于属性的 ivar 合成。也就是说,我没有声明 UITextView *textView_,但我声明了 @synthesize textView = textView_;

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

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

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

一切正常!

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:

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

Everything works fine!

作妖 2024-11-15 06:26:12

请参阅上面 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).

落花浅忆 2024-11-15 06:26:12

如果有人在将工具和设备升级到 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.

蓝梦月影 2024-11-15 06:26:11

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

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

[self->_vwHeader setHidden:NO];

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

In order to refer to an instance variable within any object other than self, including super, 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. Since CustomViewController is a subclass of BaseViewController, this scope is sufficient to access the variable using self->_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:

[self->_vwHeader setHidden:NO];

and it should work for any subclasses of the base view controller.

永言不败 2024-11-15 06:26:11

进行清理并构建,并确保您没有在构建设置中指定特定的框架搜索路径。如果将其留空,您应该获得正确的库。
好吧,我不知道,应该可以。

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

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

@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

旧人九事 2024-11-15 06:26:11

我遇到了和你类似的问题。就我而言,原因是(奇怪的是!)子类中属性的错误合成。

示例:

您有以下声明

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

在子类的 .h 文件中,当您以错误的方式合成属性时,

@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;

神奇地解决了问题!

问候

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

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

while in you synthesize the property in the wrong way:

@synthesize flag;

instead of

@synthesize flag = _flag;

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):

@interface BaseEditionModalController : NSObject 
{
    DataContext *_dataContext;
}

And I have subclass of it (excerpt):

@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

And in the LocationModalController.m I have following wrong declarations:

@implementation LocationModalController

@synthesize readLocation;
@synthesize oldLocationCommModel;

Trying to access _dataContext in LocationModalController produced the error that _dataContext is undeclared.

Changing the synthesization of properties to:

@implementation LocationModalController

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

MAGICALLY SOLVES THE PROBLEM!

Regards

在风中等你 2024-11-15 06:26:11

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

-(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 中的每个实例变量都已正确实例化。

I just stumble upon your method declaration

-(void)loadView { ... }

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:

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

Your BaseViewController.m file:

#import "BaseViewController.h"
@implementation BaseViewController

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

Your CustomViewController.h file:

@interface CustomViewController : BaseViewController {
}
@end

Your CustomViewController.m file:

#import "CustomViewController.h"

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

Now your CustomViewController can rely on every instance variable in BaseViewController is correctly instantiated.

一枫情书 2024-11-15 06:26:11

该错误表明 _vwHeader 未声明。
因此尝试修改以下代码:

CustomViewController.m

    #import "CustomViewController.h"
    @implementation CustomViewController

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

    @end

The error says that _vwHeader undeclared.
So try by modifying the code in:

CustomViewController.m

    #import "CustomViewController.h"
    @implementation CustomViewController

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

    @end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文