【问题标题】:"Compiler Bug", "Segmentation Fault 11" On Custom View Controller自定义视图控制器上的“编译器错误”、“分段错误 11”
【发布时间】:2012-07-29 01:48:45
【问题描述】:

我遇到了一个非常奇怪的问题,我想我知道为什么会遇到它,但我似乎想不出解决办法。我确信这里没有编译器错误。由于我的代码错误,我遇到过很多这样的问题。

基本上,我有一个从 UIViewController 继承的名为 UnlockKeyboardViewController 的视图控制器,以及一个名为 UnlockKeyboard 的自定义视图(直接从 UIView 继承)。 UnlockKeyboard 的标题如下所示:

@interface UnlockKeyboard : UIView
{
    NSArray *buttons;
    NSArray *passcodeFields;

    UIImage *buttonBackgroundImage;
    UIImage *buttonBackgroundHighlightedImage;
    UIImage *middleButtonBackgroundImage;
    UIImage *middleButtonBackgroundImageHighlighted;
    UIImage *screenBackgroundImage;

    UIImage *infoViewContainerImage;
    UIImage *keypadViewContainerImage;
    UIImage *passcodeFieldsContainerImage;

    UIImage *infoViewImage;
    UIImage *passcodeViewImage;

    UIView *infoViewContainer;
    UIView *keypadViewContainer;
    UIView *passcodeFieldsContainer;

    UIView *infoView;
    UIView *keypadView;
    UIView *passcodeFieldsView;

    UIView *infoToDisplayView; //The view the programmer passes to show in infoView.
}
@property(nonatomic, retain)UIImage *buttonBackgroundImage;
@property(nonatomic, retain)UIImage *buttonBackgroundHighlightedImage;
@property(nonatomic, retain)UIImage *screenBackgroundImage;
@property(nonatomic, retain)UIImage *keypadViewBackgroundImage;
@property(nonatomic, retain)UIImage *infoViewContainerImage;
@property(nonatomic, retain)UIImage *keypadViewContainerImage;
@property(nonatomic, retain)UIImage *passcodeFieldsContainerImage;
@property(nonatomic, retain)UIImage *infoViewImage;
@property(nonatomic, retain)UIImage *passcodeViewImage;
@property(nonatomic, retain)UIView *infoToDisplayView;

//Properties for container views.
@property(nonatomic, retain)UIView *infoViewContainer;
@property(nonatomic, retain)UIView *keypadViewContainer;
@property(nonatomic, retain)UIView *passcodeFieldsContainer;

@end

到目前为止,UnlockKeyboardViewController 实现如下所示:

@implementation UnlockKeyboardViewController
-(id)init
{
    if((self = [super init]))
    {
        self.view = [[UnlockKeyboard alloc] init];
    }
    return self;
}

-(void)viewDidLoad
{
    [super viewDidLoad];
}

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIView animateWithDuration:0.7 animations:^{
        self.view.keypadViewContainer.frame = CGRectMake(0, 261, 320, 200);
    } completion:^(BOOL finished){

    }];
}

-(void)dealloc
{
    [super dealloc];
}
@end

这是我的问题变得有趣。每当我尝试编译时,终端(这是一个越狱应用程序,所以没有 Xcode)给我以下错误:

In function ‘void __-[UnlockKeyboardViewController viewDidAppear:]_block_invoke_1(void*)’:
Segmentation fault: 11
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://developer.apple.com/bugreporter> for instructions.

但是,这个错误只有在我有这行时才会出现:

self.view.keypadViewContainer.frame = CGRectMake(0, 261, 320, 200);

如果我的动画块中没有那行,编译器不会给我那个错误,它会编译得很好。虽然,不管我放这条线,我总是得到分段线 11。

我认为这可能与 UIView 没有名为 keypadViewContainer 的成员这一事实有关,尽管 UnlockKeyboard 具有该属性并且是 UIView 的子类。我相信这是因为编译器实际上无法看到 UIView 和 UnlockKeyboard 之间的类层次结构。

如果我是对的,我不知道如何解决这个问题。想了一会儿。任何帮助我解决这个问题的意见将不胜感激。

【问题讨论】:

  • 您是否在视图控制器中使用 nib 文件?如果不是,loadView 的基本实现会将UnlockKeyboardViewControllerview 属性设置为常规UIView,否定您在init 中所做的事情(您不应该真正在@ 中加载view 987654331@ 无论如何)。
  • 你说“没有 Xcode”;你用的是什么编译器?
  • omz:我认为你是对的。那么我应该尝试在 loadView 中执行此任务吗?我没有使用任何笔尖或任何东西。这是纯代码,因为我没有使用 XCode。我不将 XCode 用于越狱应用程序。 benzado:仍在使用 GCC。我只是没有使用 XCode 作为我的 IDE。
  • 是的,loadView 是加载视图的合适位置。
  • 好吧,刚刚尝试将初始化移动到 loadView 并没有成功...

标签: objective-c uiview uiviewcontroller core-animation ios5


【解决方案1】:

首先,您应该只在其loadView 方法中设置视图控制器的视图属性:

- (void)loadView
{
    self.view = [[UnlockKeyboard alloc] init];
}

这将触发其他方法,例如viewDidLoad,这些方法将期望对象已完全初始化。故事的寓意:在控制器要求您之前不要设置 view 属性。

然后,在您的 viewDidAppear: 方法中,将 view 属性封装到您正在使用的特定子类中应该避免任何警告,并希望避免奇怪的编译器崩溃:

[UIView animateWithDuration:0.7 animations:^{
    UnlockKeyboard *ukView = (UnlockKeyboard *)self.view;
    ukView.keypadViewContainer.frame = CGRectMake(0, 261, 320, 200);

您编写的代码应该触发了编译器警告,因为属性keypadViewContainer 没有在UIView 上定义(表达式self.view 的类型)。

类型转换确实有点难看,但这是必要的,因为视图控制器是一个通用的父类,不知道它控制的是哪种视图。您可能会发现定义一个无需一直进行强制转换的属性很有用:

@property (nonatomic,readonly) UnlockKeyboard *unlockKeyboardView;

以及对应的方法:

- (UnlockKeyboard *)unlockKeyboardView
{
    return self.view;
}

【讨论】:

  • 也许它应该产生一个警告。 Theos 让我养成了将警告视为错误的习惯,因此编译器在有机会向我发出警告之前就已经出故障了。话虽如此,我不确定这个解决方案,因为英国应该是这个控制器的主视图(IE,我们没有为 self.view 分配任何东西)。无论如何,我会试一试,但其他方法(viewDidLoad 等)是让我担心的方法。
  • 废话,也许我应该只使用控制器创建所有内容,而不是在视图本身中创建视图的子视图......很可能会解决这个问题。
  • @Sergio 我详细阐述了我的回答,希望能解决您的一些担忧。
  • 我通过使用控制器解决了所有问题。我最初的想法是创建一个大的 UIView,它将成为整个 UnlockKeyboard。那只会给我带来麻烦,所以我决定改变它。我知道的唯一问题是动画没有发生(除非我忘记了什么),但我解决了第一个问题。自从您启发我使用控制器以来,将您的答案标记为已选择。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-24
  • 1970-01-01
相关资源
最近更新 更多