Subclassed UIView from NIB File not typed to subclass

不想你离开。 提交于 2019-12-05 11:48:30

Swapping isa pointers is a problem if your subclasses have instance variables other than those declared in SomeClassView. Note that your nib file has an object of type SomeClassView, which means that, upon loading the nib file, the nib loader will allocate an object of that type and unmarshall it from the nib file. Changing the isa pointer to [SubViewClass class] temporarily won’t make it an object of type SubViewClass per se since what the nib loader allocates is a SomeClassView object.

That said, I don’t think there’s a reliable and automatic way to use nib files containing objects whose types need to be changed upon nib loading.

What you could do is to have your SomeClassView objects declare a delegate conforming to some protocol. This protocol would define methods for behaviour in SomeClassView that can potentially be extended. For instance,

@protocol SomeClassViewDelegate
@optional
- (void)someClassViewDidAwakeFromNib:(SomeClassView *)someClassView;
@end

Instead of subclassing SomeClassView, you’d have arbitrary objects performing whatever custom behaviour you currently have in SubClassView. For instance,

@interface SubClassViewBehaviour : NSObject <SomeClassViewDelegate>
…
@end

@implementation SubClassViewBehaviour
- (void)someClassViewDidAwakeFromNib:(SomeClassView *)someClassView {
    // whatever behaviour is currently in -[SubClassView foo]
}
@end

A SubClassViewBehaviour object would be created in code and set as the nib file’s owner upon loading the nib file, or any other IB proxy object for that matter. SomeClassView would have a delegate outlet connected to file’s owner/proxy object, and it’d invoke the delegate methods in the appropriate places. For instance,

@implementation SomeClassView
- (void)awakeFromNib {
    SEL didAwakeFromNib = @selector(someClassViewDidAwakeFromNib:);
    if ([[self delegate] respondsToSelector:didAwakeFromNib]) {
        [[self delegate] performSelector:didAwakeFromNib withObject:self];
    }
}
@end

One further remark: your code currently leaks a view object since two objects are being instantiated: one via +alloc in your code and another one via nib loading. You’re assigning the latter to self, hence the one created via +alloc is leaking. Also, I believe you’ve missed a call to super in your third code snippet.

Rather than do this from within the subclass itself why not ensure it is the right class when you first instantiate it from outside the class:

SubClass *instance = [[SubClass alloc] initWithNibName:@"SomeClassView" bundle:nil];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!