मैं आमतौर पर इंटरफ़ेस बिल्डर में अपने uiviews को बनाना और डिजाइन करना पसंद करता हूं। कभी-कभी मुझे एक एक्सब में एक एकल दृश्य बनाने की आवश्यकता होती है जिसे स्टोरीबोर्ड में कई दृश्य नियंत्रकों में पुन: उपयोग किया जा सकता है।
जवाबों:
स्विफ्ट 2.2 और एक्सकोड 7.3.1 के साथ परीक्षण किया गया
// DesignableXibView.swift
import UIKit
@IBDesignable
class DesignableXibView: UIView {
var contentView : UIView?
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
contentView = loadViewFromNib()
// use bounds not frame or it'll be offset
contentView!.frame = bounds
// Make the view stretch with containing view
contentView!.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
// Adding custom subview on top of our view (over any custom drawing > see note below)
addSubview(contentView!)
}
func loadViewFromNib() -> UIView! {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: String(self.dynamicType), bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
}
नया! स्टोरीबोर्ड में सीधे रेंडर करने की क्षमता के साथ अद्यतन उत्तर (और स्विफ्ट!)
Xcode 6.3.1 में काम करता है
'ReuseableView' नाम का एक नया UIView बनाएं
'ReuseableView' नाम से एक मिलान xib फ़ाइल बनाएँ
Xib का फ़ाइल स्वामी सेट करें
कस्टम इंस्पेक्टर में 'ReusableView' के लिए कस्टम क्लास सेट करें।
ReuseableView.xib में अपने ReuseableView.h इंटरफ़ेस के दृश्य से एक आउटलेट बनाएं
दृश्य लोड करने के लिए initWithCoder कार्यान्वयन जोड़ें और एक सबव्यू के रूप में जोड़ें।
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
// 1. load the interface
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
// 2. add as subview
[self addSubview:self.view];
// 3. allow for autolayout
self.view.translatesAutoresizingMaskIntoConstraints = NO;
// 4. add constraints to span entire view
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];
}
return self;
}
एक स्टोरीबोर्ड में अपने पुन: प्रयोज्य दृश्य का परीक्षण करें
भागो और निरीक्षण करो!
UINib(nibName: nibName, bundle: nil).instantiateWithOwner(nil, options: nil)
जो NSBundle-Version की तुलना में तेज़ है।
@IBDesignable on the class.
लागू init(frame:)
भी करना है - लेकिन इसके अलावा यह बहुत अच्छा काम करता है! supereasyapps.com/blog/2014/12/15/…
स्वीकृत उत्तर के लिए 3 और 4 अपडेट करें
1. 'DesignableXibView' नाम का एक नया UIView बनाएं
2. 'DesignableXibView' नाम से एक मिलान xib फ़ाइल बनाएँ
3. xib के फ़ाइल मालिक को सेट करें
पहचान इंस्पेक्टर में "DesignableXibView.xib"> "फ़ाइल का मालिक"> "कस्टम क्लास" को 'DesignableXibView' पर सेट करें।
4. DesignableXibView का कार्यान्वयन
import UIKit
@IBDesignable
class DesignableXibView: UIView {
var contentView : UIView!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
contentView = loadViewFromNib()
// use bounds not frame or it'll be offset
contentView.frame = bounds
// Make the view stretch with containing view
contentView.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
// Adding custom subview on top of our view
addSubview(contentView)
}
func loadViewFromNib() -> UIView! {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
5 एक स्टोरीबोर्ड में अपने पुन: प्रयोज्य दृश्य का परीक्षण करें
अपना स्टोरीबोर्ड खोलें
एक दृश्य जोड़ें
उस दृश्य के कस्टम वर्ग को सेट करें
DesignableXibView
। परिवर्तनों को देखने के लिए प्रोजेक्ट बनाएँ।
String(describing: type(of: self))
इसे सुरक्षित रूप से करना चाहिए
स्विफ्ट 2 में initWithCoder फ़ंक्शन यदि किसी को अनुवाद करने में परेशानी हो रही है:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
UINib(nibName: String(self.dynamicType), bundle: NSBundle.mainBundle()).instantiateWithOwner(self, options: nil)
self.addSubview(view)
self.view.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterY , metrics: nil, views: ["view": self.view]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterX , metrics: nil, views: ["view": self.view]))
}
बस परिवर्तित Swift
करने के लिए Objective-C
यह काम करने के लिए पर्याप्त नहीं है। स्टोरीबोर्ड में लाइव रेंडरिंग की अनुमति देने के लिए मेरे पास कठिन समय है।
पूरे कोड का अनुवाद करने के बाद, डिवाइस (या सिम्युलेटर) पर चलने पर दृश्य अच्छी तरह से लोड हो जाता है, लेकिन स्टोरीबोर्ड में लाइव रेंडरिंग काम नहीं करता है। इसका कारण यह है कि मैंने इस्तेमाल किया[NSBundle mainBundle]
जबकि इंटरफ़ेस बिल्डर को मेनबंडल तक पहुंच नहीं मिली है। इसके बजाय आपको क्या उपयोग करना है[NSBundle bundleForClass:self.classForCoder]
। बूम, लाइव प्रतिपादन अब काम करता है!
नोट: यदि आपके पास ऑटो लेआउट के साथ समस्याएँ हैं, तो अक्षम करने का प्रयास करें Safe Area Layout Guides
तो Xib में का ।
आपकी सुविधा के लिए, मैं अपना पूरा कोड यहां छोड़ देता हूं, ताकि आपको बस कॉपी / पेस्ट करना पड़े (सभी प्रक्रिया के लिए, मूल उत्तर का पालन करें ):
बॉटमबार व्यू.एच
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface BottomBarView : UIView
@end
बॉटमबार व्यू
#import "BottomBarView.h"
@interface BottomBarView() {
UIView *contentView;
}
@end
@implementation BottomBarView
-(id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self xibSetup];
}
return self;
}
-(id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self xibSetup];
}
return self;
}
-(void) xibSetup {
contentView = [self loadViewFromNib];
contentView.frame = self.bounds;
contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:contentView];
}
-(UIView*) loadViewFromNib {
NSBundle *bundle = [NSBundle bundleForClass:self.classForCoder]; //this is the important line for view to render in IB
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:bundle];
UIView *view = [nib instantiateWithOwner:self options:nil][0];
return view;
}
@end
मुझे बताएं कि क्या आप कुछ मुद्दों का सामना करते हैं, लेकिन यह लगभग बॉक्स से बाहर काम करना चाहिए :)
अगर किसी को दिलचस्पी है, तो यहां @Garfbargle के कोड चरण 4 का Xamarin.iOS संस्करण है
public partial class CustomView : UIView
{
public ErrorView(IntPtr handle) : base(handle)
{
}
[Export("awakeFromNib")]
public override void AwakeFromNib()
{
var nibObjects = NSBundle.MainBundle.LoadNib("CustomView", this, null);
var view = (UIView)Runtime.GetNSObject(nibObjects.ValueAt(0));
view.Frame = Bounds;
view.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
AddSubview(rootView);
}
}
यहाँ जवाब है कि आप सभी के साथ चाहते हैं। आप बस अपनी CustomView
कक्षा बना सकते हैं , सभी साक्षात्कार और आउटलेट के साथ एक एक्सिब में इसका मास्टर उदाहरण है। फिर आप उस क्लास को अपने स्टोरीबोर्ड या अन्य xibs में किसी भी इंस्टेंस पर लागू कर सकते हैं।
फ़ाइल के स्वामी के साथ फिडेल करने की ज़रूरत नहीं है, या आउटलेट्स को एक प्रॉक्सी से कनेक्ट करें या एक अजीब तरीके से xib को संशोधित करें, या स्वयं के सबव्यू के रूप में अपने कस्टम दृश्य का एक उदाहरण जोड़ें।
बस यह करें:
UIView
करने के लिए NibView
(या से UITableViewCell
करने के लिए NibTableViewCell
)बस!
यहां तक कि यह स्टोरीबोर्ड में डिज़ाइन समय पर आपके कस्टम दृश्य (xib से सबवेक्शंस सहित) रेंडर करने के लिए IBDesignable के साथ काम करता है।
आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं: https://medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155
और आप यहाँ खुला स्रोत BFWControls ढांचा प्राप्त कर सकते हैं: https://github.com/BareFeetWare/BFWControls
टॉम 👣