online linea instalar features descargar iphone xcode interface-builder

iphone - linea - xcode online



iPhone: crea un componente reutilizable(control) que tiene algunas piezas de Interface Builder y algún código (2)

Quiero crear un componente reutilizable (un control personalizado) para el iPhone. Consiste en varios controles estándar predispuestos en una Vista, y luego en algunos códigos asociados. Mis objetivos son:

  1. Quiero poder utilizar Interface Builder para diseñar las subvistas en mi control personalizado;
  2. De alguna manera, quiero empaquetar todo para poder arrastrar y soltar fácilmente el componente personalizado resultante en otras vistas, sin tener que volver a cablear manualmente varias salidas, etc. (Un poco de cableado manual está bien, simplemente no quiero hacer toneladas y toneladas de eso).

Déjame ser más concreto, y te digo específicamente qué se supone que debe hacer mi control. En mi aplicación, a veces necesito acceder a un servicio web para validar los datos que el usuario ingresó. Mientras espero una respuesta del servicio web, quiero mostrar un spinner (un indicador de actividad). Si los servicios web responden con un código de éxito, quiero mostrar una marca de verificación de "éxito". Si el servicio web responde con un código de error, quiero mostrar un ícono de error y un mensaje de error.

La forma de un solo uso para hacer esto es bastante sencilla: simplemente creo un UIView que contiene UIActivityIndicatorView, dos UIImages (uno para el icono de éxito y otro para el icono de error) y un UILabel para el mensaje de error. Aquí hay una captura de pantalla, con las partes relevantes marcadas en rojo:

Luego conecté las piezas a los enchufes y puse un código en mi controlador.

¿Pero cómo empaqueté esas piezas, el código y la pequeña colección de vistas, para poder reutilizarlas? Aquí hay algunas cosas que encontré que me llevan a la mitad, pero no son tan buenas:

  • Puedo arrastrar la colección de vistas y controles a la sección Objetos personalizados de la Biblioteca; luego, más tarde, puedo arrastrarlos a otras vistas. Pero (a) olvida qué imágenes se asociaron con los dos UIImages, (b) hay una gran cantidad de cableado manual de cuatro o cinco enchufes, y (c) lo más importante, esto no lleva el código. (¿Quizás haya una manera fácil de cablear el código?)
  • Creo que podría crear un IBPlugin; no estoy seguro si eso ayudaría, y parece que hay mucho trabajo, y tampoco me queda del todo claro si IBPlugins funciona para el desarrollo de iPhone.
  • Pensé: "Hmm, hay un código asociado a esto, que huele a controlador", así que intenté crear un controlador personalizado (por ejemplo, WebServiceValidatorController ) con el archivo XIB asociado. Eso en realidad parece muy prometedor, pero en ese momento no puedo entender cómo, en Interface Builder, arrastrar este componente a otras vistas. WebServiceValidatorController es un controlador, no una vista, por lo que puedo arrastrarlo a una ventana de documento, pero no a una vista.

Tengo la sensación de que me estoy perdiendo algo obvio ...


Así es como estoy resolviendo un problema similar: quería:

  • crear "clases de módulo de widgets" reutilizables e independientes que implementen una vista compleja construida a partir de múltiples componentes UIKit (¡y otras clases de módulos de widgets anidados!). A las clases de clientes de nivel superior de estas clases de widgets no les importa qué es UILabel, qué es un UIImageView internamente dentro del widget, a las clases de clientes solo les importan conceptos como "mostrar el puntaje" o "mostrar el logotipo del equipo".

  • dentro de una clase de módulo de widgets, diseñe la interfaz de usuario para el widget y las tomas de conexión utilizando el constructor de interfaces

  • para los clientes de mayor nivel de un widget, quería poder colocar el marco del widget dentro de la vista del cliente en el constructor de interfaz sin tener que diseñar complementos personalizados para IB, etc.

Estos widgets no son controladores de nivel superior: por lo tanto, no tiene sentido que sean subclases de UIViewController. Luego también está el consejo de Apple de no tener más de un VC en una pantalla visible a la vez. Además, hay tantos consejos y opiniones flotando como "MVC! MVC! Debes separar tu Vista y tu control! MVC!" que se desalienta tanto a las personas a subclasificar a UIView o colocar la lógica de la aplicación dentro de una subclase de UIView.

Pero decidí hacerlo de todos modos (subclase UIView). He estado alrededor del bloque unas cuantas veces (pero todavía bastante nuevo en el SDK / UIKit de iPhone), y soy muy sensible al diseño que es feo, y eso puede causar problemas, y francamente no veo el problema con la subclasificación de UIView y la adición de puntos de venta y acciones. De hecho, hay muchas ventajas en hacer que su widget reutilizable sea una subclase de UIView en lugar de estar basado en UIViewController:

  • Puede colocar una instancia directa de la clase de widget en el diseño del constructor de interfaz de una vista de cliente, y el marco UIView de la vista de widget se inicializará correctamente cuando la clase de cliente se cargue desde el xib. Esto es mucho más limpio para mí que poner una "vista de marcador" en el cliente, luego instanciar el módulo de widget programáticamente y establecer el marco del widget en el marcador de posición, y luego intercambiar la vista de marcador de posición para la vista del widget.

  • Puede crear un archivo xib limpio y simple para diseñar los componentes del widget en el constructor de interfaz. El propietario del archivo está configurado para su clase de widget. El archivo nib contiene una UIView raíz (vainilla) donde se presenta toda la GUI, y luego en el método awakeFromNib: del widget, esta vista de punta se agrega al widget como una subvista. Cualquier ajuste de tamaño de fotograma se puede manejar aquí, completamente dentro del código del widget, si es necesario. Al igual que:

- (void) awakeFromNib { [[NSBundle mainBundle] loadNibNamed:@"MyWidgetView" owner:self options:nil]; [self addSubview:self.view]; }

  • El widget inicializa automáticamente su interfaz de usuario utilizando el método loadNibNamed: owner: options de NSBundle en su propio método awakeFromNib, por lo que la integración del widget en clases de clientes está limpia: simplemente coloque un UIView en la vista del cliente en IB, cambie la clase de UIView a MyWidgetView, y en el init del cliente o viewDidLoad configuran los valores predeterminados en la pantalla del widget usando la API del widget que usted mismo escribe (setScore: setTeamImage: etc.)

Me parece que esencialmente no hay diferencia en el código resultante entre la subclasificación de una UIView de esta manera para hacer un "widget" reutilizable y el uso de un UIViewController. En ambos casos, los archivos .h contienen miembros de clase de widget, puntos de venta, declaraciones de acción y declaraciones de API especiales. En ambos casos, el archivo .m contiene implementaciones de acción e implementación especial de API. ¡Y la vista está separada del control, la vista está en el archivo xib!

Entonces, en resumen, esto es lo que hago para empacar widgets de vista reutilizables complejos:

  • Convierta la clase de widget en una subclase de UIView
  • Cree una instancia del widget donde desee, en otras vistas en su aplicación en IB directamente arrastrando un UIView desde la biblioteca de herramientas y cambiando la clase a su "MyWidgetClass".
  • Diseña la IU de tu widget en IB en una punta dentro de una raíz UIView.
  • en el método awakeFromNib: de la clase de widgets, cargue la interfaz de usuario del widget desde xib y haga [self addSubview:self.theXibRootView]

  • Codifique el widget como lo haría con un UIViewController: puntos de venta, acciones, API especiales

Me interesaría saber de otros sistemas estructurales para crear widgets reutilizables y cuáles son las ventajas de este enfoque.

Si el widget necesita informar eventos a la clase del cliente, simplemente use un protocolo de delegado donde el cliente establece el delegado del widget en sí mismo, al igual que en un UIViewController.


Creé construcciones similares, excepto que no uso el resultado en IB, sino que hago una instancia usando el código. Describiré cómo funciona eso, y al final le daré una pista de cómo se puede usar para lograr lo que busca.

Comienzo desde un archivo XIB vacío donde agrego una vista personalizada en el nivel superior. Configuro esa vista personalizada para ser mi clase. A continuación, en la jerarquía de vista, creo y configuro subvistas según sea necesario.

Creo todos los IBOutlets en mi clase de vista personalizada y los conecto allí. En este ejercicio, ignoro por completo al "propietario del archivo".

Ahora, cuando necesito crear la vista (generalmente en el controlador como parte de while / for-loop para crear tantos de ellos como sea necesario), uso la funcionalidad de NSBundle de esta manera:

- (void)viewDidLoad { CGRect fooBarViewFrame = CGRectMake(0, 0, self.view.bounds.size.width, FOOBARVIEW_HEIGHT); for (MBSomeData *data in self.dataArray) { FooBarView *fooBarView = [self loadFooBarViewForData:data]; fooBarView.frame = fooBarViewFrame; [self.view addSubview:fooBarView]; fooBarViewFrame = CGRectOffset(fooBarViewFrame, 0, FOOBARVIEW_HEIGHT); } } - (FooBarView*)loadFooBarViewForData:(MBSomeData*)data { NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"FooBarView" owner:self options:nil]; FooBarView *fooBarView = [topLevelObjects objectAtIndex:0]; fooBarView.barView.amountInEuro = data.amountInEuro; fooBarView.barView.gradientStartColor = data.color1; fooBarView.barView.gradientMidColor = data.color2; fooBarView.titleLabel.text = data.name; fooBarView.titleLabel.textColor = data.nameColor; return fooBarView; }

Fíjense, cómo configuré el propietario de la punta para self , no hay daño ya que no conecté el "propietario del archivo" a nada. El único resultado valioso al cargar esta punta es su primer elemento: mi vista.

Si desea adaptar este enfoque para crear vistas en IB, es bastante fácil. Implementar la carga de subvista en una vista personalizada principal. Establezca el marco de la subvista en los límites de la vista principal, de modo que tengan el mismo tamaño. La vista principal se convertirá en el contenedor para su vista personalizada real, y también una interfaz para código externo; usted solo abre las propiedades necesarias de sus subvistas, el resto está encapsulado. A continuación, solo suelta la vista personalizada en IB, configúrela para que sea su clase y la use como de costumbre.