I have a custom class inherited from UIView
@interface StatusBarView : UIView
@property (weak, nonatomic) id <ActivationStatusDelegate> delegate;
//MARK: init
- (id) initWithCustom: (struct WidgetCustom *) widget;
- (id) initWithStatus:(ActivationBtnStatus) activeStatus;
//MARK: Function
- (void) setStatus: (ActivationBtnStatus) status;
@end
and this is a part of implementation
@interface StatusBarView ()
@property (strong, nonatomic) IBOutlet UIButton *button1;
@property (strong, nonatomic) IBOutlet UIButton *button2;
- (void) createDefaultWidget;
@end
@implementation StatusBarView
ActivationBtnStatus status = noStatus;
struct WidgetCustom widget;
bool isWidgetSet = false;
- (void)awakeFromNib {
[super awakeFromNib];
if (!isWidgetSet) {
[self createDefaultWidget];
}
[self createButton];
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self createDefaultWidget];
[self createButton];
}
return self;
}
- (void)layoutSubviews {
CAShapeLayer * maskLayer1 = [CAShapeLayer layer];
maskLayer1.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerBottomRight | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;
CAShapeLayer * maskLayer2 = [CAShapeLayer layer];
maskLayer2.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerTopLeft cornerRadii: (CGSize){10.0, 10.}].CGPath;
_button1.layer.mask = maskLayer1;
_button2.layer.mask = maskLayer2;
}
- (id)initWithCustom:(struct WidgetCustom *) widget {
self = [[[NSBundle mainBundle] loadNibNamed:@"ActivationStatus" owner:nil options:nil] lastObject];
if (self) {
isWidgetSet = true;
widget = widget;
}
return self;
}
- (id)initWithStatus:(ActivationBtnStatus)activeStatus {
self = [[[NSBundle mainBundle] loadNibNamed:@"ActivationStatus" owner:nil options:nil] lastObject];
if (self) {
status = activeStatus;
}
return self;
}
}
and this is how I managed the.xib file File's Owner's class is empty and there is no outlet for that
The outlets are connected to the view instead and I set StatusBarView
class for the.xib file's view like below
Now In different ViewController I want to use this class as an IBOutlet like This without needing any more initialisation:
but the result is just a gray view. is it possible to such do such things? if yes please tell me where I'm going wrong?
Loading custom views from XIB is not as simple as it would seem to be. I created a custom class for that containing a bunch of convenience methods. So to make this work you have to let your custom view inherit from this class and set bundle
property for it, also by default your class name should be the same as XIB name
Interface
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface MLSXibLoadingView : UIView
- (instancetype)initWithWidth:(CGFloat)width;
- (instancetype)initWithHeight:(CGFloat)height;
- (instancetype)initWithXibClass:(Class)xibClass;
- (instancetype)initFromXib;
- (instancetype)commonInit;
- (void)setup;
- (void)layoutDone;
- (void)localize;
- (void)update;
- (NSLayoutConstraint *)constraintWithIdentifier:(NSString *)identifier;
- (void)setConstant:(CGFloat)constant forConstraintWithIdentifier:(NSString *)identifier;
@property (nonatomic) NSBundle *bundle;
@property (nonatomic) BOOL layoutIsDone;
@end
Implementation
#import "MLSXibLoadingView.h"
@implementation MLSXibLoadingView
- (instancetype)init
{
self = [super init];
if (self) {
self = [self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self = [self commonInit];
}
return self;
}
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (!self.subviews.count) {
return [self commonInit];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (!_layoutIsDone) {
_layoutIsDone = YES;
[self layoutDone];
}
}
- (instancetype)initWithWidth:(CGFloat)width
{
self = [self commonInitAssigningFrame:NO];
self.frame = [MLSUtils rect:self.frame scaledToWidth:width];
return self;
}
- (instancetype)initWithHeight:(CGFloat)height
{
self = [self commonInitAssigningFrame:NO];
self.frame = [MLSUtils rect:self.frame scaledToHeight:height];
return self;
}
- (instancetype)initWithXibClass:(Class)xibClass
{
return [self commonInitAssigningFrame:NO xibClass:xibClass];
}
- (instancetype)initFromXib
{
return [self commonInitAssigningFrame:NO];
}
- (instancetype)commonInit
{
return [self commonInitAssigningFrame:YES];
}
- (void)setup
{
}
- (void)layoutDone
{
}
- (void)localize
{
}
- (void)update
{
}
- (NSBundle *)bundle
{
return nil; // implement in subclasses
}
- (instancetype)commonInitAssigningFrame:(BOOL)assignFrame
{
return [self commonInitAssigningFrame:assignFrame xibClass:self.class];
}
- (instancetype)commonInitAssigningFrame:(BOOL)assignFrame xibClass:(Class)xibClass
{
NSBundle *b = [self bundle];
assert(b);
NSString *xibName = NSStringFromClass(xibClass);
assert([b pathForResource:xibName ofType:@"nib"]);
MLSXibLoadingView *xibView = [b loadNibNamed:xibName owner:nil options:nil][0];
xibView.frame = assignFrame ? self.frame : xibView.frame;
xibView.autoresizingMask = self.autoresizingMask;
xibView.translatesAutoresizingMaskIntoConstraints = self.translatesAutoresizingMaskIntoConstraints;
for (NSLayoutConstraint *constraint in self.constraints) {
id firstItem = constraint.firstItem;
if (firstItem == self) {
firstItem = xibView;
}
id secondItem = constraint.secondItem;
if (secondItem == self) {
secondItem = xibView;
}
NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:firstItem
attribute:constraint.firstAttribute
relatedBy:constraint.relation
toItem:secondItem
attribute:constraint.secondAttribute
multiplier:constraint.multiplier
constant:constraint.constant];
newConstraint.priority = constraint.priority;
newConstraint.identifier = constraint.identifier;
[xibView addConstraint:newConstraint];
}
return xibView;
}
- (NSLayoutConstraint *)constraintWithIdentifier:(NSString *)identifier
{
for (NSLayoutConstraint *constraint in self.constraints) {
if ([constraint.identifier isEqualToString:identifier]) {
return constraint;
}
}
return nil;
}
/**
* Use this method to change constraint constant with given identifier because constraints outlets get invalid
* after view exchange in commonInitAssigningFrame: method
*/
- (void)setConstant:(CGFloat)constant forConstraintWithIdentifier:(NSString *)identifier
{
for (NSLayoutConstraint *constraint in self.constraints) {
if ([constraint.identifier isEqualToString:identifier]) {
constraint.constant = constant;
break;
}
}
}
@end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.