Reutilice un uiview xib en el guión gráfico
autolayout interface-builder (7)
Normalmente me gusta crear y diseñar mis uiviews en el generador de interfaces. A veces necesito crear una vista única en un xib que pueda reutilizarse en múltiples controladores de vista en un guión gráfico.
Actualización rápida 3 y 4 a la respuesta aceptada
1. Cree una nueva UIView llamada ''DesignableXibView''
- Archivo> Nuevo> Archivo> Origen> Cocoa Touch Class> UIView
2. Cree un archivo xib coincidente llamado ''DesignableXibView''
- Archivo> Nuevo> Archivo> Interfaz de usuario> Ver
3. Establezca el propietario del archivo de xib
Seleccione "DesignableXibView.xib"> "Propietario del archivo"> establezca "Clase personalizada" en ''DesignableXibView'' en el Inspector de identidad.
- Nota: No establezca la clase personalizada de la vista en el xib. ¡Solo el propietario del archivo!
4. Implementación de 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 Pruebe su vista reutilizable en un guión gráfico
-
Abre tu storyboard
-
Agregar una vista
-
Establecer la clase personalizada de esa vista
Para cualquiera que intente adaptar la respuesta aceptada (por @Garfbargle) a Objective-C
Simplemente convertir
Swift
a
Objective-C
no es suficiente para que funcione.
He tenido dificultades para permitir la representación en vivo en Storyboard.
Después de traducir todo el código, la vista se carga bien cuando se ejecuta en el dispositivo (o simulador), pero la representación en vivo en Storyboard no funciona.
La razón de esto es que usé
[NSBundle mainBundle]
mientras que Interface Builder no tiene acceso a mainBundle.
Lo que debe usar en su lugar es
[NSBundle bundleForClass:self.classForCoder]
.
BOOM, ¡la representación en vivo funciona ahora!
Nota: si tiene problemas con el diseño automático, intente deshabilitar las
Safe Area Layout Guides
en Xib.
Para su conveniencia, dejo todo mi código aquí, para que solo tenga que copiar / pegar (para todo el proceso, siga la respuesta original ):
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
Dígame si encuentra algunos problemas, pero casi debería salir de la caja :)
Reutilice y renderice un xib en un guión gráfico.
Probado con Swift 2.2 y Xcode 7.3.1
1 ---- Cree una nueva UIView llamada ''DesignableXibView''
- Archivo> Nuevo> Archivo> Origen> Cocoa Touch Class> UIView
2 ---- Cree un archivo xib coincidente llamado ''DesignableXibView''
- Archivo> Nuevo> Archivo> Interfaz de usuario> Ver
3 ---- Establecer el propietario del archivo de la xib
- seleccione el xib
- seleccione el propietario del archivo
- establezca la clase personalizada en ''DesignableXibView'' en el Inspector de identidad.
- Nota: No establezca la clase personalizada de la vista en el xib. ¡Solo el propietario del archivo!
4 ---- Implementación de 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 ---- Pon a prueba tu vista reutilizable en un guión gráfico
- Abre tu storyboard
- Agregar una vista
- Establecer la clase personalizada de esa vista
- espera un segundo ... BOOM !!
Aquí está la respuesta que siempre has querido.
Puede crear su clase
CustomView
, tener la instancia maestra de la misma en un xib con todas las subvistas y salidas.
Luego, puede aplicar esa clase a cualquier instancia en sus guiones gráficos u otras xibs.
No es necesario jugar con el propietario del archivo, o conectar salidas a un proxy o modificar el xib de una manera peculiar, o agregar una instancia de su vista personalizada como una subvista de sí mismo.
Solo haz esto:
- Importar marco de BFWControls
-
Cambie su superclase de
UIView
aNibView
(o deUITableViewCell
aNibTableViewCell
)
¡Eso es!
Incluso funciona con IBDesignable para representar su vista personalizada (incluidas las subvistas del xib) en tiempo de diseño en el guión gráfico.
Puede leer más sobre esto aquí: https://medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155
Y puede obtener el marco de código abierto de BFWControls aquí: https://github.com/BareFeetWare/BFWControls
Tom 👣
La función initWithCoder en swift 2 si alguien tiene problemas para traducirlo:
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]))
}
Si alguien está interesado, aquí está la versión Xamarin.iOS del código Paso 4 de @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);
}
}
¡NUEVO! respuesta actualizada con capacidad de renderizar directamente en el guión gráfico (¡y rápido!)
Funciona en Xcode 6.3.1
Cree una nueva UIView llamada ''ReuseableView''
- Archivo> Nuevo> Archivo> Origen> Cocoa Touch Class> UIView
Cree un archivo xib coincidente llamado ''ReuseableView''
- Archivo> Nuevo> Archivo> Interfaz de usuario> Ver
Establecer el propietario del archivo de xib
- seleccione el xib
- seleccione el propietario del archivo
-
establezca la clase personalizada en ''ReusableView'' en el Inspector de identidad.
- Nota: No establezca la clase personalizada de la vista en el xib. ¡Solo el propietario del archivo!
Haga una salida desde la vista en ReuseableView.xib a su interfaz ReuseableView.h
- Editor asistente abierto
- Control + Arrastrar desde la vista a su interfaz
Agregue la implementación initWithCoder para cargar la vista y agregue como una subvista.
- (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;
}
Pon a prueba tu vista reutilizable en un guión gráfico
- Abre tu storyboard
- Agregar una vista
- Establecer la clase personalizada de esa vista
¡Corre y observa!