私は通常、インターフェイスビルダーでuiviewを作成および設計するのが好きです。ストーリーボードの複数のビューコントローラーで再利用できる単一のビューをxibに作成する必要がある場合があります。
回答:
Swift2.2およびXcode7.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
}
}
新着!ストーリーボードに直接レンダリングする機能を備えた更新された回答(そして迅速に!)
Xcode6.3.1で動作します
'ReuseableView'という名前の新しいUIViewを作成します
'ReuseableView'という名前の一致するxibファイルを作成します
xibののファイル所有者を設定します
IdentityInspectorでカスタムクラスを「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/...
受け入れられた答えへのSwift3&4アップデート
1.「DesignableXibView」という名前の新しいUIViewを作成します
2.「DesignableXibView」という名前の一致するxibファイルを作成します
3.xibののファイル所有者を設定します
「DesignableXibView.xib」>「ファイルの所有者」を選択し、IDインスペクターで「カスタムクラス」を「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))
これは安全に行うべきだと思います
誰かがそれを翻訳するのに問題がある場合、swift2の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]
、Interface BuilderがmainBundleにアクセスできないのに対し、私が使用したためです。代わりに使用する必要があるのは[NSBundle bundleForClass:self.classForCoder]
です。ブーム、ライブレンダリングが機能するようになりました!
注:自動レイアウトで問題が発生した場合Safe Area Layout Guides
は、Xibで無効にしてみてください。
あなたの便宜のために、私は私のコード全体をここに残します、それであなたはただコピー/貼り付けする必要があります(すべてのプロセスのために、元の答えに従ってください):
BottomBarView.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface BottomBarView : UIView
@end
BottomBarView.m
#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
クラスを作成し、そのマスターインスタンスをすべてのサブビューとアウトレットを備えたxibに含めることができます。次に、そのクラスをストーリーボードまたは他のxib内の任意のインスタンスに適用できます。
ファイルの所有者をいじったり、アウトレットをプロキシに接続したり、特殊な方法でxibを変更したり、カスタムビューのインスタンスをそれ自体のサブビューとして追加したりする必要はありません。
これを行うだけです:
UIView
するNibView
(またはからUITableViewCell
のNibTableViewCell
)それでおしまい!
IBDesignableと連携して、ストーリーボードのデザイン時にカスタムビュー(xibからのサブビューを含む)をレンダリングすることもできます。
あなたはここでそれについてもっと読むことができます:https: //medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155
そして、ここでオープンソースのBFWControlsフレームワークを入手できます:https: //github.com/BareFeetWare/BFWControls
トム👣