I am creating a UIView subclass for a notification dropdown banner. I am using a XIB to build out the view and want to assign that xib to the class when it initializes (i.e. avoiding having to do this from the calling ViewController).
Since you can't assign to 'self' in swift, how do I properly do this from within the class itself?
class MyDropDown: UIView
{
func showNotification()
{
self = UINib(nibName: nibNamed, bundle: bundle).instantiateWithOwner(nil, options: nil)[0] as? UIView
}
}
For anyone looking on how to initialize a xib from it's own class in swift, here is the best approach using a custom class initializer:
class MyCustomView: UIView
{
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
class func initWithTitle(title: String, image: UIImage? = nil) -> MyCustomView
{
var myCustomView = UINib(nibName: "MyCustomView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as? MyCustomView
myCustomView.titleLabel.text = title
if image != nil
{
myCustomView.imageView.image = image
}
//...do other customization here...
return myCustomView
}
}
My usual approach is the following:
- Set my custom-view class as
FileOwner
in the nib - Set all required outlets and actions
- Set outlet to the view in nib and name it 'contentView' in the class
- In the
init*
method - instantiate nib with owner and add subview to my custom-view object.
Here is the example of the collection header view implemented this way.
@interface Header : UITableViewHeaderFooterView
@property (nonatomic) IBOutlet UIView *contentView;
@property (weak, nonatomic) IBOutlet UILabel *labelTitle;
// other required outlets & actions
// ...
@end
#import "Header.h"
@implementation Header
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
[[NSBundle mainBundle] loadNibNamed:@"Header"
owner:self
options:nil];
[self.contentView addSubview:self.content];
UIView *subview = self.content;
self.content.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(subview);
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview]|" options:0 metrics: 0 views:viewsDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview]|" options:0 metrics: 0 views:viewsDictionary]];
}
return self;
}
@end
// UPDATE Swift example
The main idea is not to load view from the nib directly to self
but add it /view from nib/ as a subview to the self
import UIKit
class CustomView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet weak var labelTitle: UILabel!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.__loadContent()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.__loadContent()
}
private func __loadContent() {
// create nib
let nib = UINib(nibName: "CustomView", bundle: NSBundle.mainBundle())
// load outlets to self
nib.instantiateWithOwner(self, options: nil)
// add content view as a subview
self.addSubview(self.contentView)
// disable autoresizing
self.contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
// manually create constraints to fix content view inside self with 0 padding
let viewsDict: NSDictionary = ["content": self.contentView]
let vertical = NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|",
options: NSLayoutFormatOptions.allZeros,
metrics: nil,
views: viewsDict)
let horizontal = NSLayoutConstraint.constraintsWithVisualFormat("H:|[content]|",
options: NSLayoutFormatOptions.allZeros,
metrics: nil, views: viewsDict)
self.addConstraints(vertical)
self.addConstraints(horizontal)
}
}
来源:https://stackoverflow.com/questions/28201249/swift-assign-a-nib-to-self-in-class