webentwicklung-frage-antwort-db.com.de

Verwenden Sie ein Uiview Xib im Storyboard

Normalerweise möchte ich meine Ansichten im Interface Builder erstellen und gestalten. Manchmal muss ich eine einzelne Ansicht in einem Xib erstellen, die in mehreren Ansichtscontrollern in einem Storyboard wiederverwendet werden kann.

69
Garfbargle

Wiederverwenden und Rendern eines Xib in einem Storyboard.

Getestet mit Swift 2.2 & Xcode 7.3.1

1 ---- Erstellen Sie eine neue UIView mit dem Namen 'DesignableXibView'.

  • Datei> Neu> Datei> Quelle> Cocoa Touch-Klasse> UIView

2 ---- Erstellen Sie eine passende Xib-Datei mit dem Namen 'DesignableXibView'

  • Datei> Neu> Datei> Benutzeroberfläche> Ansicht

3 ---- Stellt den Dateibesitzer von xib ein

  1. wähle das Xib aus
  2. wählen Sie den Besitzer der Datei
  3. setzen Sie die benutzerdefinierte Klasse im Identity Inspector auf 'DesignableXibView'. 

Setting a Xib's Owner to a Custom Class

  • Hinweis: Legen Sie nicht die benutzerdefinierte Klasse der Ansicht auf der XIB fest. Nur der Dateieigentümer!

4 ---- Implementierung von DesignableXibView

//  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
    }

}

5 ---- Testen Sie Ihre wiederverwendbare Ansicht in einem Storyboard

  1. Öffne dein Storyboard
  2. Ansicht hinzufügen
  3. Legen Sie die benutzerdefinierte Klasse dieser Ansicht fest
  4. warte mal ... BOOM !!

Xib Rendering Inside a Storyboard View Controller

118
Garfbargle

NEU! aktualisierte Antwort mit der Möglichkeit, direkt im Storyboard zu rendern (und Swift!)

Funktioniert in Xcode 6.3.1

Erstellen Sie eine neue UIView mit dem Namen 'ReuseableView'}

  • Datei> Neu> Datei> Quelle> Cocoa Touch-Klasse> UIView

Erstellen Sie eine passende Xib-Datei mit dem Namen 'ReuseableView'}

  • Datei> Neu> Datei> Benutzeroberfläche> Ansicht

Legt den Dateibesitzer der Xib fest

  1. wähle das Xib aus
  2. wählen Sie den Besitzer der Datei
  3. setzen Sie die benutzerdefinierte Klasse im Identity Inspector auf 'ReusableView'. enter image description here

    • Hinweis: Legen Sie nicht die benutzerdefinierte Klasse der Ansicht auf dem Xib fest. Nur der Dateieigentümer!

Machen Sie einen Auslass aus der Ansicht in der ReuseableView.xib zu Ihrer ReuseableView.h-Schnittstelle

  1. Öffnen Sie den Assistenten-Editor
  2. Strg + Ziehen Sie aus der Ansicht in Ihre Benutzeroberfläche

enter image description here

Fügen Sie die initWithCoder-Implementierung hinzu, um die Ansicht zu laden und als Unteransicht hinzuzufügen.

- (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;
}

enter image description here

Testen Sie Ihre wiederverwendbare Ansicht in einem Storyboard

  1. Öffne dein Storyboard
  2. Ansicht hinzufügen
  3. Legen Sie die benutzerdefinierte Klasse dieser Ansicht fest

enter image description here

Lauf und beobachte!enter image description here

70
Garfbargle

Swift 3 & 4 Update auf die akzeptierte Antwort

1. Erstellen Sie eine neue UIView mit dem Namen 'DesignableXibView'

  • Datei> Neu> Datei> Quelle> Cocoa Touch-Klasse> UIView

2. Erstellen Sie eine passende Xib-Datei mit dem Namen 'DesignableXibView'

  • Datei> Neu> Datei> Benutzeroberfläche> Ansicht

3. Setze den Dateibesitzer des xib

Wählen Sie "DesignableXibView.xib"> "Eigentümer der Datei"> setzen Sie "Benutzerdefinierte Klasse" im Identitätsinspektor auf "DesignableXibView".

  • Anmerkung: Legen Sie nicht die benutzerdefinierte Klasse der Ansicht auf dem Xib fest. Nur der Dateiinhaber!

4. Implementierung von 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 (over any custom drawing > see note below)
        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 Teste deine wiederverwendbare Ansicht in einem Storyboard

  • Öffne dein Storyboard 

  • Ansicht hinzufügen

  • Legen Sie die benutzerdefinierte Klasse dieser Ansicht fest

46
harsh_v

Die initWithCoder-Funktion in Swift 2, falls jemand Probleme beim Übersetzen hat:

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]))
    }
11
Ankit Goel

Für alle, die versuchen, die akzeptierte Antwort (von @Garfbargle) an Objective-C anzupassen

Es reicht nicht aus, Swift in Objective-C zu konvertieren, damit es funktioniert. Es fiel mir schwer, Live-Rendering in Storyboard zuzulassen.

Nachdem der gesamte Code übersetzt wurde, ist die Ansicht auf dem Gerät (oder im Simulator) gut geladen, aber das Live-Rendering in Storyboard funktioniert nicht. Der Grund dafür ist, dass ich [NSBundle mainBundle] verwendet habe, während Interface Builder keinen Zugriff auf mainBundle hat. Was Sie stattdessen verwenden müssen, ist [NSBundle bundleForClass:self.classForCoder]. BOOM, Live-Rendering funktioniert jetzt!

Hinweis: Wenn Sie Probleme mit dem automatischen Layout haben, deaktivieren Sie Safe Area Layout Guides in der Xib.

Für Ihre Bequemlichkeit lasse ich meinen gesamten Code hier, so dass Sie nur kopieren/einfügen müssen (für alle Prozesse folgen Sie ursprüngliche Antwort ):

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

Sag mir, wenn du auf ein paar Probleme stößt, aber es sollte fast funktionieren :)

1
AnthoPak

Wenn jemand interessiert ist, hier die Xamarin.iOS - Version des Codes Schritt 4 von @Garfbargle 

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);
        }
    }
0
Yohan Dahmani

Hier ist die Antwort, die Sie schon immer haben wollten. Sie können einfach Ihre Klasse CustomView erstellen und die Master-Instanz davon in einer xib mit allen Unteransichten und Ausgängen haben. Dann können Sie diese Klasse auf alle Instanzen in Ihren Storyboards oder anderen xibs anwenden.

Sie müssen nicht mit dem Besitzer von File herumspielen, keine Outlets mit einem Proxy verbinden oder die xib auf besondere Weise ändern oder eine Instanz Ihrer benutzerdefinierten Ansicht als Unteransicht von sich selbst hinzufügen.

Mach einfach folgendes:

  1. Importieren Sie das BFWControls-Framework
  2. Ändere deine Superklasse von UIView zu NibView (oder von UITableViewCell zu NibTableViewCell)

Das ist es!

Es funktioniert sogar mit IBDesignable, um Ihre benutzerdefinierte Ansicht (einschließlich der Unteransichten aus der xib) zur Entwurfszeit im Storyboard zu rendern.

Sie können hier mehr darüber lesen: https://medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155

Das Open-Source-Framework für BFWControls erhalten Sie hier: https://github.com/BareFeetWare/BFWControls

Tom ????

0
barefeettom