子类化自定义 UIView - 如何初始化

Posted

技术标签:

【中文标题】子类化自定义 UIView - 如何初始化【英文标题】:Subclassing a custom UIView - How to init 【发布时间】:2012-08-12 13:00:59 【问题描述】:

假设我有两个视图,MyViewMySubview,它们都是 UIView 的子类。

查看.h:

@interface MyView : UIView <ProgressCallback>
@property (retain, nonatomic) IBOutlet UIProgressBar *progress;

- (id) initWithFrame: (CGRect) frame;
- (void) progressUpdated: (NSNumber) newProgress;

@end

查看.m

@implementation MyView
@synthesize progress = _progress;

- (id)initWithFrame:(CGRect)frame;

    self = [super initWithFrame:frame];

    if (self)
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"MyViewNibFile"
                                                              owner:nil
                                                            options:nil];

        if ([arrayOfViews count] < 1)
            [self release];
            return nil;
        

        View *newView = [[arrayOfViews objectAtIndex:0] retain];
        [newView setFrame:frame];

        [self release];
        self = newView;

        self.progress.progress = .25 // This will work and change it.
    

    return self;


- (void) progressUpdated: (NSNumber) newProgress 
     self.progress.progress = newProgress.floatValue; // This also works!

我通过浏览 Apple 的文档和 *** 发现了这种创建 UIView 子类的方法。它可以工作,我可以根据回调设置我的进度,它会出现等。我的问题是当我想子查看它时。

MySubview.h

@interface MySubview : MyView
@property (retain, nonatomic) IBOutlet UIImageView *image;
@end

MySubview.m

@implementation 我的子视图

- (id)initWithLabel: (UIImageView *) image andWithFrame:(CGRect)frame;

    self = [super initWithFrame:frame];

    if (self)
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"MySubViewNibFile"
                                                              owner:nil
                                                            options:nil];

        if ([arrayOfViews count] < 1)
            [self release];
            return nil;
        

        MySubbiew *newView = [[arrayOfViews objectAtIndex:0] retain];
        [newView setFrame:frame];

        [self release];
        self = newView;

        self.progress.progress = .25 // This will work and change it.
        self.image = image; // Also works
    

    return self;

无论我如何初始化我的子类,我都无法让进度条在子类中工作。我可以在init的时候设置它,它不是nil,但它显然与我认为init之后的不对应。我认为这与我正在释放自我这一事实有关,但如果我想返回 View 类型的类,我看不到任何其他选择。我使用相同风格的 init,只是将类名更改为 Subview。回调实际上被调用并更改了代码,但它不会更新显示。笔尖中的所有东西都正确连接,除了大小之外,它们都是相同的,在这种情况下,还有一个图像。

(我尽力让示例代码尽可能简单明了。如果我没有成功,请告诉我,我会更新它。)

如何正确继承 UIView?我阅读了文档,没有任何启发,但请随时为我指明正确的方向。具体来说,我必须覆盖什么才能让所有内容都指向正确的项目?也就是显示屏上的那些。

【问题讨论】:

Cocoa-touch 和 cocoa 不一样,所以这个问题不应该做相应的编辑。 self = newView;这不会破坏继承。如果您以后想要子类化 MySubview,您的初始化程序将返回 MySubview 类,而不是您要创建的新类。 【参考方案1】:

initWithLabel:andWithFrame: 方法中调用 initWithFrame: 后,您将覆盖 self 的值

这一行:

self = newView;

覆盖在 MyView 超类 init 方法中创建的 self 的值,因此您将失去所有自定义

【讨论】:

【参考方案2】:

如果你也有这个问题,你可能做错了,因为我是。

一般:

如果您在弄乱内容,请覆盖 UIViewController

如果你弄乱了几何,覆盖UIView

这解决了我的问题,尽管从技术上讲,我的代码有什么问题是 wattson12 所说的。

【讨论】:

以上是关于子类化自定义 UIView - 如何初始化的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIView 的子类中同时覆盖 initWithFrame: 和 initWithCoder:?

如何在 Swift 1.2 中初始化自定义 UIView

如何初始化从 xib 加载的 UIView 子类?继承问题

从 UIView 子类访问 UINavigationController

从 XIB 问题动态实例化自定义 UIView(此代码有啥问题)?

自定义 UIView 子类添加 nib 子视图