4

I have many reusable views designed with nibs, all of them subclasses of a class NibView

class NibView: UIView {

var view: UIView!

func setupNib(nibName:String) {
    view = loadViewFromNib(nibName)
    view.frame = bounds
    view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
    addSubview(view)
}

func loadViewFromNib(nibName:String) -> UIView {
    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: nibName, bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
    return view
}

}

Which I subclass like this

@IBDesignable class ExampleView: NibView {

@IBOutlet weak var label: UILabel!

private var _property:Int = 0
@IBInspectable var property:Int {
    set {
        _property = newValue
        label.text = "\(newValue)"
    } get {
        return _property
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

func setup() {
    setupNib("ExampleView")
}

override func layoutSubviews() {
    super.layoutSubviews()
    // custom init

}
}

In the NIB file, I set the File's owner as ExampleView. Everything works perfectly and both storyboards and xibs render everything live.

Now, doing the same thing in Objective-C, doesn't work

IB_DESIGNABLE

@interface ExampleView : NibView

@property (nonatomic) IBInspectable NSUInteger count;

@end


@implementation NibView

- (void)setupNib:(NSString *)nibName {
    self.view = [self loadViewFromNib:nibName];
    self.view.frame = self.bounds;
    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self addSubview:self.view];
}

- (UIView *)loadViewFromNib:(NSString *)nibName {
    UIView *view = [[[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil] objectAtIndex:0];
    return view;
}

@end

And

@implementation ExampleView

- (id)init {
     self = [super init];
     if(self) {
        [self setup];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame {
     self = [super initWithFrame:frame];
     if(self) {
        [self setup];
    }
     return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
     self = [super initWithCoder:aDecoder];
     if(self) {
        [self setup];
    }
     return self;

}

- (void)setup {
    [self setupNib:@"ExampleView"];
     // Custom init
}

Any idea?

Cristian Pena
  • 2,139
  • 1
  • 19
  • 31
  • I had the same issue in the end I changed deployment target from IOS7 to IOS8 and it fixed the problem, (also you can debug it Editor-> Debug Selected Views and see where crash happens), just curious if it was the same problem for u. – Mike.R Oct 04 '15 at 19:56

1 Answers1

3

I know the question is old, but I had a similar problem, and as there are not many examples on this for Objective C, I would like to share my solution.

You are not using the same code in Objective C as in SWIFT. In Objective C you are trying to access the main bundle, but when trying to load the view in the IB, there is no main bundle. This piece of code works for me:

NSBundle *bundle = [NSBundle bundleForClass:self.classForCoder];
self.view = [[bundle loadNibNamed:@"HighscoreLabelView" owner:self options:nil] objectAtIndex:0];
dpalmetz
  • 31
  • 2
  • Wow, thanks a lot ! I was having hard time with `IB_DESIGNABLE` in `Obj-C` and it was all due to this ! Thanks for registering on SO to share this ! Welcome to the community :) – AnthoPak Mar 19 '19 at 13:15
  • Thank you! After what feels like an endless search through UIView and Swift examples, this, this right here is the missing link that just saved my sanity. =) – ParvusM Oct 01 '19 at 15:40