2011-02-23 12 views
16

Estoy diseñando con IB un botón específico (con algunas etiquetas, y imageView y otras cosas).Usando el objeto xib dentro de otra xib

Me gustaría utilizar ese objeto xib (el botón) en otro xib, donde tengo 6 objetos de ese botón.

Sé que puedo hacerlo programáticamente usando el identificador de clase, pero luego tengo que posicionar mis etiquetas y vista de imagen, y establecer los valores predeterminados y todo lo demás en el código.

Me pregunto si es posible hacer lo mismo con solo el IB? (Por supuesto, aun así, establecer los valores de código, pero quiero posiciones de los lables/imageView y todo lo demás que se establezcan en el xib)

Gracias

Editar

Así , Entiendo que lo que pedí al principio no es posible. Lo que intento ahora es así:

Creé un ButtonTest.xib. Dentro del Xib tengo una UIView y 3 subvistas (2 etiquetas y un botón). En el inspector configuré la clase UIView en ButtonTest. Inside ButtonTest.m Tengo 3 salidas para cada una de las subvistas, que conecto en IB.

Siguiente Tengo un ButtonTestViewController.xib. Dentro de él puse una vista y configuré su clase en el inspector para que sea ButtonTest. conecto ese punto de vista a una toma de myTextView dentro de la clase ButtonTestViewController.mButtonTest

Ahora, este es el código dentro de ButtonTestViewController.m viewDidLoad:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"ButtonTest" owner:nil options:nil]; 
    ButtonTest *mainView = (ButtonTest*)[subviewArray objectAtIndex:0]; 

    self.myTextView = mainView; 
} 

lo que esperaba que iba a pasar, es que la vista en ButtonTestViewController. xib se convertiría en la vista que diseñé en ButtonTest.xib. Esto simplemente no está sucediendo. lo que sucede es que la vista dentro de ButtonTestViewController.xib permanece igual.

Vale la pena mencionar, es que si añado:

[self.view addSubview:mainView]; 

se le añade el nuevo punto de vista, además de la ya existente.

¿Alguna idea de cómo hacer lo que quiero?

Eventualmente me gustaría tener 6 vistas en ButtonTestViewController.xib, todas se verían como la plantilla ButtonTest.xib, y los valores de las etiquetas se establecerán en el código.

Edit2

Ok chicos, he hecho todo lo que dijeron y funcionó como un encanto. El único problema que tengo ahora con este problema es cuando la vista en ButtonTestViewController.xib es un poco más grande que la vista en ButtonTest.xib. Cuando eso sucede, la etiqueta del botón luce extremadamente borrosa. Cuando ambos son del mismo tamaño, todo está bien.

@ Ned - He utilizado el código exacto que ha escrito en mi método InitWithCoder, salvo que cambié la frase trama a esto:

self.bounds = mainView.frame; 

He intentado jugar con el modo de contenido en IB tratando de solucionarlo, a Sin resultado.

Cuando hago utilizarlo como informados, lo que significa:

mainView.frame = self.bounds; 

No está funcionando en absoluto, y tamaños de ambos puntos de vista de permanecer igual. Aquí traté de jugar con resizeMask, pero aún así no funcionó.

¿Y la idea de cómo solucionar estos 2 problemas? ¡Gracias chicos!

Datos 3

Me las arreglé para fijar uno de los temas, cambiar el tamaño de la ButtonTestViewController.xib al tamaño ButtonTest.xib vista. Esto es lo que hice (utilizando el código para resolver el problema borrosa, tomada de here)

self.bounds = CGRectMake(0, 0, mainView.frame.size.width, mainView.frame.size.height); 
     CGRect overlay2Frame = self.frame; 
     overlay2Frame.origin.x = round(overlay2Frame.origin.x); 
     overlay2Frame.origin.y = round(overlay2Frame.origin.y); 
     self.frame = overlay2Frame; 

El otro problema que no puede resolver. la vista en ButtonTest.xib simplemente no se agrandará para coincidir con la otra vista.

Respuesta

15

Puede hacerlo, y con bastante facilidad. La forma en que hago esto es crear una subclase UIView (digamos que se llama "MyView.m" y "MyView.h"), y luego una punta llamada "MyView.xib".

Primero, en la punta, haga clic en Propietario del archivo y configure la clase en "Mi Vista". Esto hará que IBOutlets/Actions de tu clase aparezcan en IB. Agregue una única vista de nivel superior (si no tiene una ya) como su vista principal, y agregue sus otros elementos personalizados (UILabels y UIImageViews) como subvistas de la UIView principal.

A continuación, agregue el siguiente código para que se invoque cuando se inicialice MyView (recuerde, si inicializa desde un plumilla, se inittará desde - (id) initWithCoder: (NSCoder *) aDecoder).

NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil]; 
UIView *mainView = [subviewArray objectAtIndex:0]; 

//Just in case the size is different (you may or may not want this) 
mainView.frame = self.bounds; 

[self addSubview:mainView]; 

Lo que esto hace es cargas de la jerarquía de vistas de su plumín en el NSArray, y ya que sólo tenían un UIView de nivel superior, que acaba de añadir que como una vista secundaria de la UIView personalizado.

Esto le permite diseñar UIViews (y otras subclases de UIView) en Interface Builder.

EDITAR: Se ha actualizado a la edición de OP.

La forma en que siempre he hecho esto es siguiendo primero mis instrucciones anteriores. Una diferencia es que en su plumilla ButtonTest está cambiando la clase de UIView a ButtonTest, pero cambio la clase del propietario del archivo a ButtonTest. Luego, dentro de ButtonTest.m, haz lo de loadNibNamed. Ahora, para agregar ese objeto al ButtonTestViewController.xib, agregue un UIView (o UIButton, cualquiera que sea la subclase de ButtonTest) y cambie la clase a ButtonTest.

Esto es un poco confuso, así que intentaré dividirlo por archivo.

ButtonTestViewController.xib: Añadir una UIButton (de cualquier ButtonTest hereda de) y cambiar la clase a ButtonTest

ButtonTest.m: Dentro del método "initWithCoder", hacer todas las cosas "loadNibNamed" Tengo anterior

ButtonTest.xib: cambie la clase Propietario de archivo a ButtonTest y enlace todos IBOutlets e IBActions

+0

Creo que la OP ha llegado hasta aquí ya. Él está preguntando cómo usar MyView.xib en otros archivos .xib y poder editar completamente la interfaz personalizada. –

+0

Matt tiene razón, aunque edité la pregunta con una nueva pregunta. por favor echa un vistazo. – Idan

+0

He editado mi respuesta para ser un poco más claro. Creo que esto es lo que estás buscando hacer. – Ned

-1

Si su clase es una subclase de UIButton por ejemplo, puede abrir la Biblioteca en Interface Builder y estará debajo de la pestaña de clases cuando busque eso y puedes arrastrar y soltar.

También puede simplemente arrastrar/soltar un UIButton y establecer su clase en el panel del inspector.

Sin embargo, porque tiene su propio .xib que podría estropearlo, en cuyo caso simplemente ignóreme.

5

Algunos de ustedes preguntan en comentario si esta solución no crear bucle infinito y no tengo la reputación suficiente para responder allí, así que aquí está mi respuesta:

El bucle si existen vista raíz en su XI ter tiene "Clase personalizada" establecida en MyView. Esto provoca la situación en la que la vista cargada desde XIB invoca el inicializador de MyView de nuevo y, por lo tanto, crea un bucle infinito. La solución es que la "clase personalizada" debe ser UIView y solo la clase del propietario del archivo debe establecerse en MyView (para poder asignar IBOutlets e IBActions).

1

Swift 3.0

crear el archivo con la clase rápida

class ViewXIBfileClassView: UIView { 
..... 
} 

crear Xib archivo con vista: ViewXIBfileClassView

crear clase de vista envoltorio

class ViewWrapper: UIView { 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     let view = UINib(nibName: "ViewXIBfileClassView_file", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! viewXIBfileClassView 
     self.addSubview(view) 
     view.bindEdgesToSuperview() 
    } 
} 

extensión añadir a UIView

extension UIView { 
    /// Adds constraints to the superview so that this view has same size and position. 
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this. 
    func bindEdgesToSuperview() { 
     guard let superview = superview else { 
      preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.") 
     } 
     translatesAutoresizingMaskIntoConstraints = false 
     ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in 
      superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self])) 
     } 
    } 
} 

Uso UIView con ViewWrapper dentro de todos los archivos que desea xib