自定義視圖控制器上的“編譯器錯誤”、“分段錯誤 11” ("Compiler Bug", "Segmentation Fault 11" On Custom View Controller)


問題描述

自定義視圖控制器上的“編譯器錯誤”、“分段錯誤 11” ("Compiler Bug", "Segmentation Fault 11" On Custom View Controller)

I'm having a very weird problem, that I think I know why I'm getting it but I can't seem to think of a fix. I am convinced there is no compiler bug here. I have had many of those and all of them occurred because of my faulty code.

Basically, I have a view controller called UnlockKeyboardViewController that inherits from UIViewController, and a custom view (inheriting directly from UIView) called UnlockKeyboard. The header for UnlockKeyboard looks like this:

@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

The UnlockKeyboardViewController implementation looks like this so far:

@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

This is were my problem gets interesting. Whenever I try to compile, the Terminal (this is a jailbreak app, so no Xcode) gives me the following error:

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.

BUT, this error only appears when I have this line in:

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

If I don't that line in my animation block, the compiler won't give me that error and it wil compile just fine. Although, no matter were I put this line, I always get segmentation line 11.

I THINK this may have something to do with the fact that UIView doesn't have a member called keypadViewContainer, although UnlockKeyboard has that property and is a subclass of UIView. I believe this is happening because the compiler can't actually see the class hierarchy between UIView and UnlockKeyboard.

If I'm right, I have no idea of how to go around the problem. Been thinking for a while. Any input to help me solve this problem will be really appreciated.


參考解法

方法 1:

First, you should only set a view controller's view property in its loadView method:

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

This will trigger other methods, such as viewDidLoad, that will expect the object to have been full initialized. Moral of the story: don't set the view property until the controller asks you to.

Then, in your viewDidAppear: method, casing the view property into the specific subclass you are using should avoid any warnings and hopefully also that weird compiler crash:

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

The code as you have written it should have triggered a compiler warning, because the property keypadViewContainer isn't defined on UIView (the type of the expression self.view).

The type cast is admittedly a little bit ugly, but it's necessary since the view controller is a generic parent class and doesn't know what kind of view it is controlling. You may find it useful to define a property that eliminates the need to do the cast all the time:

@property (nonatomic,readonly) UnlockKeyboard *unlockKeyboardView;

And the corresponding method:

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

(by Andy Ibanezbenzado)

參考文件

  1. "Compiler Bug", "Segmentation Fault 11" On Custom View Controller (CC BY-SA 3.0/4.0)

#objective-c #ios5 #core-animation #uiviewcontroller #uiview






相關問題

為什麼 NSWindow 或 NSView 實例處理它自己的鍵事件,而不是它的委託? (Why does an NSWindow or NSView instance handle its own key events, and not its delegate?)

在調用之前釋放了 didFinishSelector ASIHTTPRequest 的自定義委託類 (Custom delegate class for didFinishSelector ASIHTTPRequest being deallocated before called)

通過 IKImage 視圖預覽圖像 (Previewg images via IKImage View)

Gaya Jendela Kustom di Kakao (Custom Window Style in Cocoa)

Тонкія белыя лініі дадаюцца пры абрэзцы выявы (Objective-C OSX) (Thin white lines being added when cropping an image (Objective-C OSX))

Obj-C:遞歸:在堆棧上創建新對像或使用可變性 (Obj-C: Recursion: Making new objects on stack or use mutability)

XCode 4.6 顯示方法 + (void)beginAnimations:(NSString *)animationID context:(void *)context; 的內存洩漏警告 (XCode 4.6 shows a warning of memory leak for method + (void)beginAnimations:(NSString *)animationID context:(void *)context;)

單元格中不可見的 UITextField 已將 userInteractionEnabled 設置為 No (UITextField in cell that is not visible has userInteractionEnabled set to No)

Gửi nhật ký sự cố ứng dụng / nhật ký ứng dụng thông thường (Send app crash logs/regular app logs)

我的鍵盤默認值僅在我的應用程序中更改 (My keyboard default be change in only my App)

在復選框上單擊獲取表行 ID - 目標 c (On check box click get the table Row ID - Objective c)

iPhone SDK:檢查 UITableView 中每個對象的 ID 號並相應地更改徽章號 (iPhone SDK: Checking the ID number for each object in a UITableView and change the badge number accordingly)







留言討論