簡體   English   中英

自定義UIView子類要求兩次調用awakeFromNIB

[英]Custom UIView subclass requires awakeFromNIB to be called twice

我絕望地被困住了,我會很感激指針。

我們正在嘗試構建一個包含多個視圖的視圖控制器,這些視圖是UIView的子類。 除了我們需要手動初始化視圖或再次手動調用awakeFromNib(這是不允許的)之外,一切都工作得很好。

這是問題......

Subclassed UIView頭文件:

#import <UIKit/UIKit.h>
@interface introView : UIView
@property (strong, nonatomic) UIView *view;
@property (strong, nonatomic) NSString *title;
@property (strong, nonatomic) IBOutlet UILabel *titleLabel;
@end

Subclassed UiView主文件:

#import "introView.h"

@interface introView ()
@end

@implementation introView

-(id)init
{
    NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"introView" owner:self options:nil];
    id mainView = [subviewArray objectAtIndex:0];
    return mainView;
}
- (void) awakeFromNib
{
    [super awakeFromNib];
    [self initialize];
    [self addSubview:self.view];
}

-(void)initialize
{
    NSLog(@"title: %@", self.title);
    self.titleLabel.text = self.title;
}

然后我們從視圖控制器初始化視圖:

introView *view = [[introView alloc]init];
view.title = @"Test";
[self addSubview:view];

這是問題 - 通過調用此視圖,視圖顯示正確但標題為NULL;

[43605:1957090] title: (null)

但是,如果我們再次調用awakeFromNib,則視圖會正確初始化

在視圖控制器中:

introView *view = [[introView alloc]init];
view.title = @"Test;
[self addSubview:view];
[view awakeFromNib];

然后它工作:

2014-11-21 09:33:03.500 Test[43706:1972060] title: (null)
2014-11-21 09:33:03.500 Test[43706:1972060] title: Test

或者,如果我將initialize方法設為public並在初始化后調用它也可以。 但這在我眼中打敗了目的......

在視圖控制器中:

introView *view = [[introView alloc]init];
view.title = @"Test;
[self addSubview:view];
[view initialize]; //calling the method directly...

在我看來,我們以某種方式運行到視圖還沒有准備好的情況但是它在第二次嘗試時工作(即使awakeFromNib調用是非法的)

出口設置正確,文件所有者設置...它只需要兩個awakeFromNib調用。

任何幫助表示贊賞。

---------------- UPDATE ------------------

謝謝你們,我很欣賞指針。 我按照概述實現了初始化程序,但我遇到了同樣的問題。 此外,我使用GitHub示例作為一個干凈的示例,並嘗試將變量分配給此視圖,甚至顯示相同的行為。 因此,我開始認為我在其他地方做錯了。 看這里:

//
//  SubClassView.h
//  CustomView
//
//  Created by Paul Solt on 4/28/14.
//  Copyright (c) 2014 Paul Solt. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "PSCustomViewFromXib.h"

@interface SubClassView : PSCustomViewFromXib
@property (strong, nonatomic) NSString *title;
@end

SubclassView.m

//
//  SubClassView.m
//  CustomView
//
//  Created by Paul Solt on 4/28/14.
//  Copyright (c) 2014 Paul Solt. All rights reserved.
//

#import "SubClassView.h"

@interface SubClassView()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UISwitch *onSwitch;


@end

@implementation SubClassView

// Note: You can customize the behavior after calling the super method

// Called when loading programatically
- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if(self) {
        // Call a common method to setup gesture and state of UIView
        [self setup];
    }
    return self;
}

// Called when loading from embedded .xib UIView
- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self) {
        // Call a common method to setup gesture and state of UIView
        [self setup];
    }
    return self;
}

- (void)setup {
    // Add a gesture to show that touch input works on full bounds of UIView
    NSLog(@"%@", self.title);
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    [self addGestureRecognizer:panGesture];
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
    NSLog(@"Pan: %@", NSStringFromCGPoint([gesture locationInView:gesture.view]));
}
- (IBAction)switchChanged:(UISwitch *)sender {
    NSLog(@"Switch: %d", sender.on);
}

@end

查看控制器類

//
//  ViewController.m
//  CustomView
//
//  Created by Paul Solt on 4/28/14.
//  Copyright (c) 2014 Paul Solt. All rights reserved.
//

#import "ViewController.h"
#import "SubClassView.h"
#import "LabelMadness.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];


    // Add a custom view's programmatically (position using 1/2 width and height)

    SubClassView *oneView = [[SubClassView alloc] init];
    oneView.center = CGPointMake(80 + 80, 282 + 40);
    oneView.backgroundColor = [UIColor blueColor];
    oneView.title = @"Test2";
    [self.view addSubview:oneView];

}

@end

-------輸出-----

2014-11-21 11:49:38.893 CustomView[45653:2123668] LabelMadness.initWithFrame:
2014-11-21 11:49:38.893 CustomView[45653:2123668] (null)

我在這做錯了什么?

您根本不需要使用awakeFromNib。 如果你想讓introView加載它自己的nib,你可以這樣做(將視圖的類更改為xib文件中的introView),

-(instancetype)init{
    if (self = [super init]) {
        NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"introView" owner:self options:nil];
        self = [subviewArray objectAtIndex:0];
    }
    return self;
}

要設置標題,您可以覆蓋title屬性的setter,

-(void)setTitle:(NSString *)title {
    _title = title;
    self.titleLabel.text = title;
}

控制器中的代碼與您最初嘗試的代碼相同。

那么,你有.xib或故事板中的視圖嗎?

它看起來像是來自.xib所以你應該看看這個答案

您不應該覆蓋init方法,也不應該在代碼中分配init。 如果這樣做,則不會加載您在界面構建器中創建的視圖。

所以不是使用alloc init,而是按照我指出的答案做一些類似的事情。

無論如何,我看不出你在哪里初始化你的

@property (strong, nonatomic) UIView *view;

不是IBOutlet,你永遠不會在任何地方啟動它,所以顯然總是nil

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM