Cómo cargar una UIView utilizando un file nib creado con Interface Builder

Estoy tratando de hacer algo un poco elaborado, pero algo que debería ser posible. Entonces, aquí hay un desafío para todos ustedes expertos (este foro es un package de muchos de ustedes :)).

Estoy creando un "componente" del cuestionario, que quiero cargar en un NavigationContoller (my QuestionManagerViewController ). El "componente" es un UIViewController "vacío", que puede cargar diferentes vistas según la pregunta que debe responderse.

La forma en que lo estoy haciendo es:

  1. Cree el object Question1View como una subclass UIView , que define algunos IBOutlets .
  2. Cree (usando Interface Builder) el Question1View.xib (AQUÍ ES DONDE ES PROBABLEMENTE MI PROBLEMA ). Configuré tanto el UIViewController como el UIView para ser de class Question1View.
  3. Enlace las salidas con el componente de la vista (usando IB).
  4. initWithNib el initWithNib de mi QuestionManagerViewController para que se vea así:

     - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:@"Question1View" bundle:nibBundleOrNil]) { // Custom initialization } return self; } 

Cuando ejecuto el código, obtengo este error:

2009-05-14 15: 05: 37.152 iMobiDines [17148: 20b] *** Finalización de la aplicación debido a la exception no NSInternalInconsistencyException ' NSInternalInconsistencyException ', razón: ' -[UIViewController _loadViewFromNibNamed:bundle:] cargado el -[UIViewController _loadViewFromNibNamed:bundle:] "Question1View" pero el punto de vista no se configuró '.

Estoy seguro de que hay una manera de cargar la vista usando el file nib, sin necesidad de crear una class viewController.

También hay una manera más fácil de acceder a la vista en lugar de tratar con la plumilla como una matriz.

1 ) Cree una subclass de vista personalizada con cualquier salida a la que desee tener acceso más adelante. –Mi vista

2 ) en UIViewController que desea cargar y manejar la plumilla, cree una propiedad IBOutlet que saveá la vista de la plumilla cargada, por ejemplo

en MyViewController (una subclass UIViewController)

  @property (nonatomic, retain) IBOutlet UIView *myViewFromNib; 

(no olvides sintetizarlo y liberarlo en tu file .m)

3) abra su plumín (lo llamaremos 'myViewNib.xib') en IB, configure el propietario de su file en MyViewController

4) ahora conecte la salida del propietario del file myViewFromNib a la vista principal en la punta.

5) Ahora en MyViewController, escribe la siguiente línea:

 [[NSBundle mainBundle] loadNibNamed:@"myViewNib" owner:self options:nil]; 

Ahora, tan pronto como lo hagas, llamar a tu propiedad "self.myViewFromNib" te dará acceso a la vista desde tu punta.

Gracias a todos. Encontré una manera de hacer lo que quería.

  1. Crea tu UIView con el IBOutlet que necesites.
  2. Cree el xib en IB, diseñelo a su gusto y vincúlelo de la siguiente manera: El propietario del file es de la class UIViewController (Sin subclass personalizada, pero la "real"). La vista del propietario del file está conectada a la vista principal y su class se declara como la del paso 1).
  3. Conecte sus controles con el IBOutlet .
  4. El DynamicViewController puede ejecutar su lógica para decidir qué vista / xib cargar. Una vez que hizo la decisión, en el loadView ponemos algo como esto:

     NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"QPickOneView" owner:self options:nil]; QPickOneView* myView = [ nibViews objectAtIndex: 1]; myView.question = question; 

¡Eso es!

El método loadNibNamed del package principal se encargará de inicializar la vista y crear las conexiones.

Ahora el ViewController puede mostrar una vista u otra dependiendo de los datos en la memory, y la pantalla "padre" no necesita molestarse con esta lógica.

No estoy seguro de a qué se refieren algunas de las respuestas, pero necesito poner esta respuesta aquí cuando busco en Google la próxima vez. Palabras key: "Cómo cargar una UIView desde una punta" o "Cómo cargar una UIView desde una NSBundle".

Aquí está el código casi 100% directamente desde el libro Apress Beginning iPhone 3 (página 247, "Uso de la nueva celda de vista de tabla"):

 - (void)viewDidLoad { [super viewDidLoad]; NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"Blah" owner:self options:nil]; Blah *blah; for (id object in bundle) { if ([object isKindOfClass:[Blah class]]) { blah = (Blah *)object; break; } } assert(blah != nil && "blah can't be nil"); [self.view addSubview: blah]; } 

Esto supone que tienes una subclass UIView llamada Blah , una punta llamada Blah que contiene una UIView que tiene su class establecida en Blah .


Categoría: NSObject + LoadFromNib

 #import "NSObject+LoadFromNib.h" @implementation NSObject (LoadFromNib) + (id)loadFromNib:(NSString *)name classToLoad:(Class)classToLoad { NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:name owner:self options:nil]; for (id object in bundle) { if ([object isKindOfClass:classToLoad]) { return object; } } return nil; } @end 

Para todos aquellos que necesitan administrar más de una instancia de la vista personalizada, es decir, una Outlet Collection , combiné y personalicé las respuestas @Gonso, @AVeryDev y @Olie de esta manera:

  1. Cree una MyView : UIView personalizada MyView : UIView y MyView : UIView como " Clase personalizada " de la UIView raíz en el XIB deseado; clase personalizada

  2. Cree todos los puntos de venta que necesite en MyView (hágalo ahora porque después del punto 3, el IB le propondrá que conecte los puntos de venta al UIViewController y no a la vista personalizada como queramos); salida de clase personalizada

  3. Establezca su UIViewController como " Propietario del file " de la vista personalizada XIB ; introduzca la descripción de la imagen aquí

  4. En UIViewController agregue una nueva UIViews para cada instancia de MyView que desee y conéctelas a UIViewController creando una colección de UIViewController : estas vistas actuarán como vistas "envolventes" para las instancias de vista personalizadas; introduzca la descripción de la imagen aquí

  5. Finalmente, en la viewDidLoad de su UIViewController agregue las siguientes líneas:

 NSArray *bundleObjects; MyView *currView; NSMutableArray *myViews = [NSMutableArray arrayWithCapacity:myWrapperViews.count]; for (UIView *currWrapperView in myWrapperViews) { bundleObjects = [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil]; for (id object in bundleObjects) { if ([object isKindOfClass:[MyView class]]){ currView = (MyView *)object; break; } } [currView.myLabel setText:@"myText"]; [currView.myButton setTitle:@"myTitle" forState:UIControlStateNormal]; //... [currWrapperView addSubview:currView]; [myViews addObject:currView]; } //self.myViews = myViews; if need to access them later.. 

Utilizaría UINib para crear una UIView personalizada para reutilizar

 UINib *customNib = [UINib nibWithNibName:@"MyCustomView" bundle:nil]; MyCustomViewClass *customView = [[customNib instantiateWithOwner:self options:nil] objectAtIndex:0]; [self.view addSubview:customView]; 

Los files necesarios en este caso son MyCustomView.xib , MyCustomViewClass.h y MyCustomViewClass.m Tenga en count que [UINib instantiateWithOwner] devuelve una matriz, por lo que debe usar el elemento que refleja la UIView que desea reutilizar. En este caso, es el primer elemento.

No debe configurar la class de su controller de vista para que sea una subclass de UIView en Interface Builder. Eso es definitivamente al less parte de su problema. Deje eso como UIViewController , alguna subclass de él u otra class personalizada que tenga.

En cuanto a cargar solo una vista desde un xib, estaba bajo el supuesto de que tenía que tener algún tipo de controller de vista (incluso si no extiende UIViewController , que puede ser demasiado pesado para sus necesidades) configurado como propietario del file en Interface Builder si quiere usarlo para definir su interfaz. Hice un poco de investigación para confirmar esto también. Esto es porque, de lo contrario, no habría forma de acceder a ninguno de los elementos de la interfaz en la UIView , ni habría una forma de que sus propios methods en el código se desencadenaran por events.

Si utiliza un UIViewController como propietario de su file para sus vistas, puede usar initWithNibName:bundle: para cargarlo y recuperar el object del controller de vista. En IB, asegúrese de configurar el view venta de la vista con su interfaz en el xib. Si utiliza algún otro tipo de object como propietario de su file, deberá usar el NSBundle loadNibNamed:owner:options: método de loadNibNamed:owner:options: para cargar la punta, pasando una instancia del propietario del file al método. Todas sus properties se configurarán correctamente de acuerdo con los puntos de venta que usted define en IB.

También puede usar initWithNibName de UIViewController en lugar de loadNibNamed. Es más simple, lo encuentro.

 UIViewController *aViewController = [[UIViewController alloc] initWithNibName:@"MySubView" bundle:nil]; [self.subview addSubview:aViewController.view]; [aViewController release]; // release the VC 

Ahora solo tiene que crear MySubView.xib y MySubView.h / m. En MySubView.xib, establezca la class Propietario del file en UIViewController y vea la class en MySubView.

Puede colocar y tamaño de la subview utilizando el file padre xib.

Esta es una gran pregunta (+1) y las respuestas fueron casi útiles;) Lo siento, chicos, pero tuve un buen rato perdiendo el time, aunque tanto Gonso como AVeryDev dieron buenas pistas. Con suerte, esta respuesta ayudará a otros.

MyVC es el controller de vista que contiene todas estas cosas.

MySubview es la vista que queremos cargar desde una xib

  • En MyVC.xib, cree una vista del tipo MySubView que tenga el tamaño y la forma adecuados y se posicione donde lo desee.
  • En MyVC.h, tienes

     IBOutlet MySubview *mySubView // ... @property (nonatomic, retain) MySubview *mySubview; 
  • En MyVC.m, @synthesize mySubView; y no te olvides de lanzarlo en dealloc .

  • En MySubview.h, tenga una salida / propiedad para la UIView *view (puede ser innecesario, pero funcionó para mí). Sintetice y libérelo en .m
  • En MySubview.xib
    • establezca el tipo de propietario de file en MySubview y vincule la propiedad de vista a su vista.
    • IBOutlet todos los bits y conéctate a IBOutlet como se desee
  • De vuelta en MyVC.m, tienes

     NSArray *xibviews = [[NSBundle mainBundle] loadNibNamed: @"MySubview" owner: mySubview options: NULL]; MySubview *msView = [xibviews objectAtIndex: 0]; msView.frame = mySubview.frame; UIView *oldView = mySubview; // Too simple: [self.view insertSubview: msView aboveSubview: mySubview]; [[mySubview superview] insertSubview: msView aboveSubview: mySubview]; // allows nesting self.mySubview = msView; [oldCBView removeFromSuperview]; 

Lo difícil para mí fue: las pistas en las otras respuestas cargaron mi vista desde el xib, pero NO replaceon la vista en MyVC (¡duh!), Tuve que cambiar eso por mi count.

Además, para get acceso a los methods de mySubview , la propiedad de view en el file .xib debe estar configurada en MySubview . De lo contrario, vuelve como una UIView antigua.

Si hay una manera de cargar mySubview directamente desde su propio xib, eso se movería, pero esto me consiguió donde necesitaba estar.

Esto es algo que debería ser más fácil. Terminé extendiendo UIViewController y agregando un loadNib:inPlaceholder: selector. Ahora puedo decir

 self.mySubview = (MyView *)[self loadNib:@"MyView" inPlaceholder:mySubview]; 

Aquí está el código de la categoría (hace el mismo rigamarole que describe Gonso):

 @interface UIViewController (nibSubviews) - (UIView *)viewFromNib:(NSString *)nibName; - (UIView *)loadNib:(NSString *)nibName inPlaceholder:(UIView *)placeholder; @end @implementation UIViewController (nibSubviews) - (UIView *)viewFromNib:(NSString *)nibName { NSArray *xib = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil]; for (id view in xib) { // have to iterate; index varies if ([view isKindOfClass:[UIView class]]) return view; } return nil; } - (UIView *)loadNib:(NSString *)nibName inPlaceholder:(UIView *)placeholder { UIView *nibView = [self viewFromNib:nibName]; [nibView setFrame:placeholder.frame]; [self.view insertSubview:nibView aboveSubview:placeholder]; [placeholder removeFromSuperview]; return nibView; } @end 

Yo también quería hacer algo similar, esto es lo que encontré: (SDK 3.1.3)

Tengo un controller de vista A (propio de un controller de Nav) que carga el VC B en un button. Presione:

En AViewController.m

 BViewController *bController = [[BViewController alloc] initWithNibName:@"Bnib" bundle:nil]; [self.navigationController pushViewController:bController animated:YES]; [bController release]; 

Ahora VC B tiene su interfaz de Bnib, pero cuando se presiona un button, quiero ir a un 'modo de edición' que tiene una UI separada de una punta diferente, pero no quiero un nuevo VC para el modo de edición, Quiero que la nueva punta se asocie con mi B VC existente.

Entonces, en BViewController.m (en el método de presionar button)

 NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"EditMode" owner:self options:nil]; UIView *theEditView = [nibObjects objectAtIndex:0]; self.editView = theEditView; [self.view addSubview:theEditView]; 

Luego, en otro button, presione (para salir del modo de edición):

 [editView removeFromSuperview]; 

y he vuelto a mi Bnib original.

Esto funciona bien, pero tenga en count mi EditMode.nib tiene solo 1 obj de nivel superior, un object UIView. No importa si el propietario del file en esta punta se establece como BViewController o el NSObject pnetworkingeterminado, PERO asegúrese de que el Outlet de vista en el propietario del file NO esté configurado en nada. Si es así, obtengo un error exc_bad_access y xcode procede a cargar 6677 ttwigs de stack que muestran un método UIView interno repetidamente llamado … así que parece un bucle infinito. (El View Outlet está configurado en mi Bnib original, sin embargo)

Espero que esto ayude.

Hice una categoría que me gusta:

UIView+NibInitializer.h

 #import <UIKit/UIKit.h> @interface UIView (NibInitializer) - (instancetype)initWithNibNamed:(NSString *)nibNameOrNil; @end 

UIView+NibInitializer.m

 #import "UIView+NibInitializer.h" @implementation UIView (NibInitializer) - (instancetype)initWithNibNamed:(NSString *)nibNameOrNil { if (!nibNameOrNil) { nibNameOrNil = NSStringFromClass([self class]); } NSArray *viewsInNib = [[NSBundle mainBundle] loadNibNamed:nibNameOrNil owner:self options:nil]; for (id view in viewsInNib) { if ([view isKindOfClass:[self class]]) { self = view; break; } } return self; } @end 

Entonces, llame así:

 MyCustomView *myCustomView = [[MyCustomView alloc] initWithNibNamed:nil]; 

Use un nombre de nib si su punta se llama algo diferente al nombre de su class.

Para anularlo en tus subclasss para un comportamiento adicional, podría verse así:

 - (instancetype)initWithNibNamed:(NSString *)nibNameOrNil { self = [super initWithNibNamed:nibNameOrNil]; if (self) { self.layer.cornerRadius = CGRectGetHeight(self.bounds) / 2.0; } return self; } 

En swift

En realidad, mi resolución de este problema era cargar la vista en una vistaDidLoad en mi CustonViewController donde quería usar la vista así:

 myAccessoryView = NSBundle.mainBundle().loadNibNamed("MyAccessoryView", owner: self, options: nil)[0] as! MyAccessoryView 

¡No cargue la vista en un método loadView() ! El método loadView sirve para cargar la vista para su ViewController personalizado.

Encontré este blog publicado por Aaron Hillegass (autor, instructor, Cocoa ninja) para ser muy esclarecedor. Incluso si no adoptas su enfoque modificado para cargar files NIB a través de un inicializador designado, probablemente al less obtendrás una mejor comprensión del process que está sucediendo. He estado usando este método últimamente para un gran éxito.

La respuesta anterior no tiene en count un cambio en la estructura NIB (XIB) que se produjo entre 2.0 y 2.1 del iPhone SDK. Los contenidos del usuario ahora comienzan en el índice 0 en lugar de 1.

Puede usar la macro 2.1 que es válida para todas las versiones 2.1 y superiores (son dos guiones bajos antes de IPHONE:

  // Cited from previous example NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"QPickOneView" owner:self options:nil]; int startIndex; #ifdef __IPHONE_2_1 startIndex = 0; #else startIndex = 1; #endif QPickOneView* myView = [ nibViews objectAtIndex: startIndex]; myView.question = question; 

Usamos una técnica similar a esta para la mayoría de nuestras aplicaciones.

Barney

Tenía motivos para hacer lo mismo (cargar una vista desde un file XIB mediante progtwigción), pero tenía que hacerlo completamente desde el context de una subclass de una subclass de una UIView (es decir, sin involucrar al controller de vista de ninguna manera). Para hacer esto, creé este método de utilidad:

 + (id) initWithNibName:(NSString *)nibName withSelf:(id)myself { NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:myself options:nil]; for (id object in bundle) { if ([object isKindOfClass:[myself class]]) { return object; } } return nil; } 

Entonces lo llamo desde mi subclass 'método initWithFrame así:

 - (id)initWithFrame:(CGRect)frame { self = [Utilities initWithNibName:@"XIB1" withSelf:self]; if (self) { // Initialization code. } return self; } 

Publicado por interés general; Si alguien ve algún problema sin hacerlo de esta manera, avíseme.

Para el usuario Swift con opción de layout:

  1. Cree una subclass UIView personalizada y un file xib , que nombraremos después de nuestro propio nombre de class: en nuestro caso MemeView. Dentro de la class de la vista Meme, recuerde definirla como designable con el atributo @IBDesignable antes de la statement de class
  2. Rember para configurar el propietario del file en el xib con nuestra subclass UIView personalizada en el panel Inspector de indeterminación

    introduzca la descripción de la imagen aquí

  3. En el file xib ahora podemos build nuestra interfaz, crear restricciones, crear puntos de venta, acciones, etc. introduzca la descripción de la imagen aquí

  4. Necesitamos implementar algunos methods para nuestra class personalizada para abrir el xib una vez inicializado

    class XibbedView: UIView {

     weak var nibView: UIView! override convenience init(frame: CGRect) { let nibName = NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last! self.init(nibName: nibName) } requinetworking init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) let nibName = NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last! let nib = loadNib(nibName) nib.frame = bounds nib.translatesAutoresizingMaskIntoConstraints = false addSubview(nib) nibView = nib setUpConstraints() } init(nibName: String) { super.init(frame: CGRectZero) let nibName = NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last! let nib = loadNib(nibName) nib.frame = bounds nib.translatesAutoresizingMaskIntoConstraints = false addSubview(nib) nibView = nib setUpConstraints() } func setUpConstraints() { ["V","H"].forEach { (quote) -> () in let format = String(format:"\(quote):|[nibView]|") addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(format, options: [], metrics: nil, views: ["nibView" : nibView])) } } func loadNib(name: String) -> UIView { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: name, bundle: bundle) let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView return view } 

    }

  5. En nuestra class personalizada también podemos definir algunas properties inspeccionables para tener un control total sobre ellas desde el creador de interfaces

    @IBDesignable class MemeView: XibbedView {

     @IBInspectable var memeImage: UIImage = UIImage() { didSet { imageView.image = memeImage } } @IBInspectable var textColor: UIColor = UIColor.whiteColor() { didSet { label.textColor = textColor } } @IBInspectable var text: String = "" { didSet { label.text = text } } @IBInspectable var roundedCorners: Bool = false { didSet { if roundedCorners { layer.cornerRadius = 20.0 clipsToBounds = true } else { layer.cornerRadius = 0.0 clipsToBounds = false } } } @IBOutlet weak var label: UILabel! @IBOutlet weak var imageView: UIImageView! 

}

Pocos ejemplos:
introduzca la descripción de la imagen aquí introduzca la descripción de la imagen aquí

Si necesitamos agregar más información a la vista mientras se muestra dentro de un storyboard u otro xib, para hacerlo podremos implementar prepareForInterfaceBuilder() , este método se ejecutará solo mientras se abre el file en el generador de interfaces. Si hiciste todo lo que escribí pero nada funciona, es una forma de depurar una vista sigle mediante la adición de puntos de interrupción en su implementación. introduzca la descripción de la imagen aquí
Aquí está la jerarquía de vistas. Ver hiearchy

Espero que esto ayude a download una muestra completa aquí.

Aquí hay una manera de hacerlo en Swift (actualmente escribiendo Swift 2.0 en XCode 7 beta 5).

Desde su subclass UIView que configuró como "Clase personalizada" en el Generador de interfaces, cree un método como este (mi subclass se llama RecordingFooterView):

 class func loadFromNib() -> RecordingFooterView? { let nib = UINib(nibName: "RecordingFooterView", bundle: nil) let nibObjects = nib.instantiateWithOwner(nil, options: nil) if nibObjects.count > 0 { let topObject = nibObjects[0] return topObject as? RecordingFooterView } return nil } 

Entonces puedes llamarlo así:

let recordingFooterView = RecordingFooterView.loadFromNib()

Ninguna de las respuestas explica cómo crear el XIB autónomo que es la raíz de esta pregunta. No hay Xcode 4 opción Xcode 4 para "Crear un nuevo file XIB".

Para hacer esto

 1) Choose "New File..." 2) Choose the "User Interface" category under the iOS section 3) Choose the "View" item 4) You will then be prompted to choose an iPhone or iPad format 

Esto puede parecer simple, pero puede ahorrarle unos pocos minutos hurgando, ya que la palabra "XIB" no aparece en ninguna parte.

@AVeryDev

6) Para adjuntar la vista cargada a la vista del controller de vista:

 [self.view addSubview:myViewFromNib]; 

Presumiblemente, es necesario eliminarlo de la vista para evitar pérdidas de memory.

Para aclarar: el controller de vista tiene varios IBOutlets, algunos de los cuales están conectados a elementos en el file original de nib (como es habitual), y algunos están conectados a elementos en la punta cargada. Ambas nibs tienen la misma class de propietario. La vista cargada se superpone a la original.

Sugerencia: establezca la opacidad de la vista principal en la punta cargada en cero, entonces no oscurecerá los elementos de la punta original.

Después de pasar muchas horas, falsifiqué la siguiente solución. Siga estos pasos para crear UIView personalizado.

1) Crear class myCustomView henetworkingada de UIView .
introduzca la descripción de la imagen aquí

2) Cree .xib con el nombre myCustomView .
introduzca la descripción de la imagen aquí

3) Cambia la class de UIView dentro de tu file .xib, asigna myCustomView Class allí.
introduzca la descripción de la imagen aquí

4) Crear IBOutlets
introduzca la descripción de la imagen aquí

5) Cargue .xib en myCustomView * customView . Use el siguiente código de muestra.

 myCustomView * myView = [[[NSBundle mainBundle] loadNibNamed:@"myCustomView" owner:self options:nil] objectAtIndex:0]; [myView.description setText:@"description"]; 

Nota: Para aquellos que aún se enfrentan problema puede comentar, les proporcionaré enlace de proyecto de ejemplo con myCustomView

Tengo una convención de nombrar xibs con vistas en ellas lo mismo que la vista. Lo mismo que uno haría para un controller de vista. Entonces, no tengo que escribir nombres de class en el código. Cargo una UIView desde un file de nib con el mismo nombre.

Ejemplo para una class llamada MyView.

  • Cree un file de nib llamado MyView.xib en Interface Builder
  • En Interface Builder, agregue una UIView. Establezca su class en MyView. Personalice el contenido de su corazón, conecte las variables de instancia de MyView a las subvenciones a las que desee acceder más tarde.
  • En su código, cree un nuevo MyView así:

    MyView * myView = [MyView nib_viewFromNibWithOwner: propietario];

Aquí está la categoría para esto:

 @implementation UIView (nib) + (id) nib_viewFromNib { return [self nib_viewFromNibWithOwner:nil]; } + (id) nib_viewFromNibWithOwner:(id)owner { NSString *className = NSStringFromClass([self class]); NSArray *nib = [[NSBundle mainBundle] loadNibNamed:className owner:owner options:nil]; UIView *view = nil; for(UIView *v in nib) { if ([v isKindOfClass:[self class]]) { view = v; break; } } assert(view != nil && "View for class not found in nib file"); [view nib_viewDidLoad]; return view; } // override this to do custom setup -(void)nib_viewDidLoad { } 

A continuación, conecté botones con acciones del controller que estoy usando y puse tags en las tags en la subclass de vista personalizada.

Terminé de agregar una categoría a UIView para esto:

  #import "UIViewNibLoading.h" @implementation UIView (UIViewNibLoading) + (id) loadNibNamed:(NSString *) nibName { return [UIView loadNibNamed:nibName fromBundle:[NSBundle mainBundle] retainingObjectWithTag:1]; } + (id) loadNibNamed:(NSString *) nibName fromBundle:(NSBundle *) bundle retainingObjectWithTag:(NSUInteger) tag { NSArray * nib = [bundle loadNibNamed:nibName owner:nil options:nil]; if(!nib) return nil; UIView * target = nil; for(UIView * view in nib) { if(view.tag == tag) { target = [view retain]; break; } } if(target && [target respondsToSelector:@selector(viewDidLoad)]) { [target performSelector:@selector(viewDidLoad)]; } return [target autorelease]; } @end 

explicación aquí: viewcontroller es less vista cargando en ios y mac