2011-06-06 9 views
7

De acuerdo, sé que esta es una pregunta conceptual vaga, pero realmente necesito ayuda aquí. Gracias de antemano si decides tomarte el tiempo para leer esto. Yo nunca consideraría escribir mucho, excepto que este es un gran foro con tanta gente útil que pensé que este sería el mejor lugar para preguntar.¿Cómo puedo "conectar" una vista de tabla a un controlador de vista

Todo esto se relaciona con la pregunta aquí (que no tiene que mirarlo - explico todo lo siguiente): Pass parameter when initializing table

que he estado trabajando durante días en el mismo problema, pero estoy dándome cuenta de que debe haber algo grande que me estoy perdiendo. Busqué en Google y busqué en Google e incluso compré (y aproximadamente el 50% leí) dos libros de Obj-C hace unos días, pero aún me aferro a algo que parece que debería ser increíblemente fácil. Obviamente soy bastante nuevo en OOP, pero tengo habilidades mediocres en HTML, perl, sql, python, así como algunas de las cosas antiguas como pascal y básica. Soy un n00b, pero no un idiota (bueno, en realidad esta experiencia está cambiando mi mente un poco).

De todos modos, mi objetivo final es simplemente crear una aplicación con 8 botones "normales" en la primera vista (nivel 1), haciendo básicamente lo mismo - mostrar una vista de tabla simple (nivel 2) con datos en celdas en los que se puede hacer clic para continuar profundizando en los detalles (nivel 3). Concepto muy básico y directo. La única diferencia entre los 8 posibles niveles 2 es la información que se mostrará. Ya he construido consultas sql que funcionan igual que quiero para cada botón.

Por lo tanto, aquí es donde estoy parado: tengo una aplicación que funciona perfectamente y que hace todo desde el nivel 2 exactamente como yo esperaba - las consultas funcionan, las tablas son hermosas - así que es genial.

Además, tengo otra aplicación basada en la navegación que se inicia en "nivel 1" y me muestra 8 botones (oculto la barra de navegación en el nivel 1). Si hago clic en cualquiera de los botones en el nivel 1, la vista de nivel 2 (que es una barra de navegación + una tabla) se desliza a la vista exactamente como quiero. El problema es que la mesa está en blanco. No importa lo que haga, no puedo obtener el nivel 2 en la segunda aplicación para mostrarme los datos, a pesar de que puedo mostrar todos esos datos en la primera aplicación a la perfección. Por mi vida, no puedo encontrar la manera de "vincular" el nivel 1 con el nivel 2.

Espero que puedan entender esta brecha que estoy tratando de salvar. Como hay 8 posibilidades para el nivel 2 (con solo diferencias muy pequeñas en las consultas sql en la misma tabla sql), inicialmente traté de encontrar una forma de "pasar" un entero a la vista de nivel 2 (en la primera aplicación) y luego seleccionando la consulta sql basada en lo que se pasó (ver el enlace arriba para ese fiasco). Una vez que obtuve ese funcionamiento, planeé averiguar cómo hacer que los botones hagan el "paso" más tarde. Sin embargo, después de aproximadamente 16 horas jugando con eso, me di por vencido y decidí hacer 8 diferentes controladores de vista de tabla, todos con código casi idéntico excepto la consulta. De esa forma, si pudiera obtener un botón SINGLE en el nivel 1 para simplemente presionar a UNO de los niveles 2 sin parámetros, sería un programador horrible pero exitoso.

Lamentablemente, incluso eso no me ha funcionado. He intentado todas las combinaciones posibles de control-arrastre y ventana/vista/tabla que se me ocurren en Interface Builder, pero no importa lo que intento, los datos nunca se cargan en la vista de tabla, aunque funciona muy bien en mi primera aplicación. He revisado cada línea de código: son lo mismo, excepto que algo tiene que "llamar" o "lanzar" la parte del nivel 2 y simplemente no la obtengo.

Por lo tanto, voy a romper con las convenciones/expectativas aquí y no publicar ningún código en mi pregunta. Solo quiero saber, ¿cómo puede ser esto tan difícil? Tengo una mentalidad muy analítica y entiendo rápidamente, pero debo decir que nunca me sentí tan humilde por un desafío técnico en mi vida.

¿Alguien puede explicarme, a nivel conceptual, qué debo hacer aquí o qué me falta? Incluso si me das un enlace a algo para leer, lo agradecería mucho. He visto decenas de horas de tutoriales en youtube, pero siempre estoy dispuesto a recibir más.

Por supuesto que estoy dispuesto a compartir mi código, pero hay tanto y soy muy nuevo en esto, realmente no sé dónde están las partes relevantes. Además, en realidad quiero aprender cómo funciona todo esto para poder ayudar a los demás. Si hay algo como PM aquí, se lo enviaré si está dispuesto a echar un vistazo. Una vez que lo haga funcionar, publicaré el código aquí. Tengo que creer que hay otras personas buscando el mismo tipo de cosas que yo. Sin embargo, lo que es más importante, solo quiero saber, desde un alto nivel, ¿cuál es la forma correcta de abordar mi problema? Si miran mi enlace, pueden ver lo que he estado intentando (que era pasar un número entero al método que puebla la tabla), pero como dije, básicamente me rendí porque no estaba llegando a ningún lado. La gente está tratando de ayudarme, pero soy un idiota.

Gracias por llevar mi mensaje agonizantemente largo. Si llegaste tan lejos y tienes algunas sugerencias para mí, soy todo oídos. Sin embargo, seré sincero. Si me dices que debería descartar todo y usar datos básicos, lloraré. Realmente no creo que tenga tiempo para descubrir una forma completamente diferente de administrar datos. Como dije, estoy muy contento con la base de datos y las partes de la consulta de mi aplicación, ¡solo está gestionando las vistas desquiciadas y pasando datos entre ellas que me están matando!

Se agradece cualquier ayuda, muchas gracias a todos.

+2

¿Por qué el voto a favor? La pregunta es perfectamente legal y no es solo otra pregunta de tarea. – JustSid

+0

@truthsmiles - Estaré encantado de explicarle esto, no dude en hacerme un seguimiento en el chat de Google. (moshberm) Mientras tanto, voy a intentar escribir una respuesta. – Moshe

+2

@Moshe, -1 si pudiera, decirle a alguien que discuta en privado va en contra de todo el modelo SO porque nunca ayudará a nadie más. – Pops

Respuesta

4

Si entiendo su pregunta correctamente, está preguntando cómo inicializar un controlador de vista y pasar algunos datos para alterar su comportamiento. El concepto clave aquí para comprender es cómo se inicializan los objetos en Objective-C. Una de las preguntas más comunes que los desarrolladores que son nuevos en iOS tienen es:

HowcanIpassdatabetweenmyviews?

Sí, ocho enlaces diferentes allí. (Bien, ese octavo enlace está un poco fuera de tema, pero está lo suficientemente cerca.) Hay varias formas de hacerlo y las revisaré brevemente. También describiré los inicializadores personalizados, que también son un punto relevante.

Imaginemos que estábamos creando una aplicación de catálogo que muestra un grupo de productos en diversas categorías. Imagine que nuestra aplicación se abre a una lista de productos, al igual que la aplicación Apple Store. Digamos que cuando el usuario toca un producto, queremos mostrar una página de producto.

  1. Puede establecer propiedades en la "próxima" controlador de vista. - Simplemente, podemos crear una subclase UIViewController y establecer la propiedad productID (que inventamos). Llamemos a nuestro nuevo UIViewController a ProductPageViewController. Así es como se vería esto:

    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 
    
        //Create a ProductPageViewController 
        ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:@"ProductPageViewController" bundle:nil]; 
        //set the property on our ProductPageViewController 
        [ppvc setProductID:42]; 
        //We would usually present the PPVC here. 
        //After presenting, remember to release the view controller 
    } 
    

    En la primera línea, creamos el controlador de vista del producto. Llamamos al alloc, luego al init. (Las funciones están ajustadas, es decir, llamamos al init directamente en el resultado del método alloc).

    Luego, establecemos una propiedad de nuestra vista.La vista ahora se puede configurar en viewWillAppear y todo está bien.

  2. Puede compartir los datos en una tienda permanente. - Este método funciona de manera diferente. Los controladores de vista no se comunican en absoluto, a excepción de la primera que presenta una segunda. Siempre que un valor en la primera vista cambia (que desea persistir), lo escribe en Core Data o NSUserDefaults. Luego, la nueva vista lee el valor según lo necesita.

    En su primer controlador de vista:

    //A method to store the data 
    - (void)storeData:(id)pageID{ 
        [[NSUserDefaults setObject:pageID forKey:@"pageID"]; 
    } 
    
    - (void)showNewPPVC{ 
    
        ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:@"ProductPageViewController" bundle:nil];   
        //Show and then release the PPVC 
    } 
    
  3. Puede utilizar inicializadores personalizados.: esta es probablemente la forma más intuitiva de hacerlo, una vez que comprenda el concepto, porque este es el único en el que los datos se "pasan". (A diferencia del método 2 donde no se comparten datos directamente y el método 1 donde los datos se pasan como una propiedad.)

    Observe que en los ejemplos anteriores, utilicé el método initWithNibName:Bundle. También puede observar que UITableViewController s utiliza un inicializador diferente, initWithStyle:. Esos dos inicializadores toman información del nuevo objeto para que sepa cómo cargarlo. Veamos el primero primero:

    - (id)initWithNibName:(NSString *)nibNameOrNil Bundle:(NSBundle *)bundleNameOrNil; 
    

    El primer argumento le dice al controlador de vista qué archivo de punta cargar. Voy a ignorar el segundo argumento por ahora, ya que nunca he visto nada aprobado excepto nil. La derecha móvil adelante con el segundo ejemplo:

    - (id)initWithStyle:(UITableViewStyle)style; 
    

    Puede pasar en uno de los dos valores UITableViewStyle aquí. Esta es una forma de definir el estilo de una vista de tabla (a la inversa, modificar un archivo de punta directamente).

    Extendemos un poco este concepto a nuestro ejemplo. Ahora voy a mostrarte cómo crear tu propio inicializador personalizado. Inicialicemos nuestra instancia ProductPageViewController:

    - (id) initWithProductID:(int)productID; 
    

    Eso es bastante simple. Ahora, debemos implementar el método y realmente hacer algo con la identificación del producto. Comenzaremos con el código barebones aquí, necesario para "imitar" la funcionalidad del inicializador predeterminado.

    - (id) initWithProductID:(int)productID{ 
    self = [super init]; 
    
    return self; 
    } 
    

    Este método devolverá una copia de nuestra inicializado ProductPageViewController, sin embargo, no va a cargar hasta nuestra interfaz de usuario de una SEMILLA todavía, o si esto fuera un UITableViewController, no sería establecer el UITableViewStyle. Primero trabajemos con un NIB y luego le mostraré cómo trabajar un UITableViewController. Entonces ...

    - (id) initWithProductID:(int)productID{ 
    self = [super initWithNibName:@"ProductPageViewController" Bundle:nil]; 
    
    return self; 
    } 
    

    Ahora. tenemos un ProductPageViewController inicializado, cargado desde un NIB, pero aún no hace nada. Observe cómo no exponemos los argumentos NibName y Bundle, pero simplemente los pasamos en nosotros mismos. Si quieres, en teoría podrías exponerlos también. Ahora tomemos el productID y hagamos algo al respecto.

    - (id) initWithProductID:(int)productID{ 
    self = [super initWithNibName:@"ProductPageViewController" Bundle:nil]; 
    
        if(self){ 
        self.prodID = productID; 
        } 
    
    return self; 
    } 
    

    Con nuestros últimos cambios, nuestra "PPVC" ahora sabe acerca de la productID. Puede consultar la base de datos como desee y hacer cosas con los resultados. A continuación, puede ejecutar diferentes consultas basadas en este productID.

Dos Más consejos rápidos:

  1. Tal vez quieren transmitir en varios argumentos. Por supuesto, puede simplemente agregarlos a la firma del método - (id) initWithProductID:(int)productID andCategoryID(int)categoryID, pero ¿qué sucede si tiene cinco, seis o cincuenta y seis (sí, eso es mucho) argumentos? Aconsejo pasar una colección o conjunto de argumentos.

  2. Para utilizar los inicializadores personalizados con UITableView, pase un UITableViewStyle en lugar de un nombre NIB. Esto es lo que podría parecer:

     - (id) initWithProductID:(int)productID{ 
         self = [super initWithStyle:UITableViewStyleGrouped]; 
    
         if(self){ 
          self.prodID = productID; 
         } 
    
         return self; 
         } 
    

Al hacer sus subsecciones, sugeriría una combinación de datos persistentes y inicializadores personalizados. También aconsejo echar un vistazo a los métodos viewDidLoad y viewWillAppear.

Cuestiones relacionadas