¿Cómo identifico un model, una vista y un controller en el objective c?

Viniendo de Ruby en los Rails en el sublime editor de text, mi layout de carpeta tenía el model, la vista y las carpetas del controller y su layout hacía que fuera fácil identificar qué era qué.

En objective-c, acabo de crear un nuevo proyecto para un nuevo tutorial que estoy siguiendo. Tengo los files:

BullsEyeViewController.h BullsEyeViewController.m BullsEyeViewController.xib

Parece que el file xib es la vista. Sé que el file .h es para declaraciones y .m para mi implementación para esas declaraciones. ¿Se clasificarán estos 2 files como el controller?

Si es así, ¿cómo identificaría un model? Completé el aburrido pero necesario libro de progtwigción objective-c del gran rancho-nerd, pero aún me encuentro un poco confundido cuando se trata de MVC en el objective c.

Ahora estoy haciendo otro curso y pensé aclarar esto de una vez por todas. En Ruby sobre Rails, como dije, puedo identificar fácilmente los models de vistas y controlleres, pero en objetive-c cuando trato de comenzar a confundirme.

¿xib es una vista? pero tiene un controller de visión en su nombre que me retuerce un poco. Agradecería un poco de ayuda para aclarar todo esto. Digamos que quería crear un file que se ocupara de todo mi almacenamiento y se comunicara con el db … ¿cómo se vería eso en cuanto a la estructura del nombre del file?

También puse los files appdelegate en la carpeta de soporte por ahora para confundir less cosas. Lo que me gustaría hacer es crear una carpeta de model, vista y controller y colocar los files relacionados dentro de ellos.

Ningún lenguaje de progtwigción realmente hace cumplir la separación de MVC. Los frameworks como Ruby of Rails ayudan a guiarte hacia la separación de MVC usando el lenguaje Ruby.

Puede mover files de forma segura a carpetas sin mucho problema para que su proyecto sea más fácil de entender.

En UIKit, ocurre lo siguiente:

Puntos de vista

Los objects UIView son generalmente vistas. Las UIViews se pueden asociar con cero a un UIViewController. UIView se puede serializar como un file XIB o un storyboard.

Controladores

UIViewController es el controller de vista. Los objects que implementan UIApplicationDelegate son el controller de los controlleres para la aplicación principal. UIViewController también puede subclass de forma que sea también un controller de controlleres como UISplitViewController, UINavigationController y UITabBarController.

Entonces, ¿por qué el nombre Xcode XIB presenta el mismo nombre que el UIViewController correspondiente?

La implementación de loadView de loadView busca files XIB en el package especificado en tres fases.

  1. Para una nib llamada nibName si nibName no es nil en el package especificado.
  2. Para una punta nombrada el nombre de la class less la palabra "Controlador" en el package especificado.
  3. Para una punta nombrada el nombre de la class en el package especificado.

Es por eso que al anular loadView en una subclass, no se cargan loadView .

Por lo tanto, puede cambiar el nombre de sus files XIB de forma segura para eliminar la palabra "Controlador" y todo seguirá funcionando siempre y cuando su UIViewController no especifique un valor en su propiedad nibName . Por qué Apple decidió hacer que Xcode eligiera el tercer caso como el valor pnetworkingeterminado cuando se crea automáticamente una punta con un controller.

Modelos

Los models suelen ser subclasss de NSObject. Cuando utiliza Core Data, los models son subclasss de NSManagedObject. El file xml que crea es como un file nib: es solo una serialization de los metadatos de sus models.

Solo mantengo esta estructura.

 |view |--all the .xib's and Storyboard |Controller |--All the View Controller both .h and .m file |model |--.h and .m file for each controller which would be call models. 

Ejemplo.

 |view |--login.xib |Controller |--loginViewController.h |--loginViewController.m |model |--loginModel.h |--loginModel.m 

En LoginModel, normalmente manejo las llamadas API y convierto a todos los json para que obliguen a NSMutableDictionary y envíen datos al controller para un procesamiento posterior.

En My loginController realizará operaciones sobre los datos recibidos.

Ejemplo: estoy usando AFNetworking para llamadas API.

AFHTTPAPliente.h

 #import "AFHTTPClient.h" #import "AFJSONRequestOperation.h" @interface AFHTTPAPIClient : AFHTTPClient + (AFHTTPAPIClient *)shanetworkingClient; @end 

AFHTTPAPIClient.m

 #import "AFHTTPAPIClient.h" @implementation AFHTTPAPIClient // Singleton Instance + (AFHTTPAPIClient *)shanetworkingClient { static AFHTTPAPIClient *shanetworkingClient = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shanetworkingClient = [[AFHTTPAPIClient alloc] initWithBaseURL:[NSURL URLWithString:@"www.yourdomain.com"]]; }); return shanetworkingClient; } - (id)initWithBaseURL:(NSURL *)url { self = [super initWithBaseURL:url]; if (!self) { return nil; } [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; [self setDefaultHeader:@"Accept" value:@"application/json"]; return self; } @end 

loginModel.h

 #import "AFHTTPAPIClient.h" + (void)loginWith:(NSDictionary *)parameters withBlock:(void (^)(NSMutableDictionary *, NSError *))block; 

LoginModel.m

 + (void)loginWith:(NSDictionary *)parameters withBlock:(void (^)(NSMutableDictionary *, NSError *))block { [[AFHTTPAPIClient shanetworkingClient] postPath:@"/api/login" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject){ NSLog(@"%@",responseObject); if (block) { block(responseObject, nil); } } failure:^(AFHTTPRequestOperation *operation,NSError *error){ if (block) { block([NSArray array], error); } }]; } 

y luego, finalmente, utilícelos en Controladores.

loginViewController.m

 NSDictionary * loginParametes = [[NSDictionary alloc] initWithObjectsAndKeys:_txtUsername.text,@"username", _txtPassword.text,@"password",nil]; [LoginModel loginWith:loginParametes withBlock:^(NSMutableDictionary *loginInfo, NSError *error) { if (!error) { if([[loginInfo objectForKey:@"status"] boolValue]==YES){ // Login Success } else { // Login Failure } } else { // API Responce failure if content type is not a valid json or valid status code. } }]; 

Esto es de lo que he entendido en las últimas semanas sobre el paradigma de MVC en iOS. El patrón de layout de MVC en la progtwigción de iOS sigue un enfoque ligeramente diferente cuando se implementa en el objective C, en comparación con otros idiomas. Su class BullsEyeViewController es su controller según el paradigma MVC. Su file .xib es su opinión. Xcode sigue el patrón de nombrar tus files según las classs que especifiques en la window del proyecto de creación. Sus classs model implementarán su lógica de aplicaciones. La mayor parte de su gestión de bases de datos será manejada por su controller. Para cumplir con el MVC aquí, deberá crear sus classs model de manera diferente. Las classs model notificarán al controller. El controller hará el trabajo de actualizar las vistas y los models. y respondiendo a las acciones del usuario en la vista.

XCode no hace cumplir las estructuras de MVC de la misma manera que Rails, como has visto. Han pasado algunos años desde que trabajé con Rails, por lo que puede estar desactualizado, pero esto es lo que recuerdo: cuando inicia un proyecto Rails puede proporcionar files de database, y Rails los usará para generar objects model que describan el entidades de database, junto con vistas para ver / editar esos objects model y controlleres para conectar los models y las vistas.

Cuando crea una nueva aplicación de vista única en XCode, no genera ningún file model para usted. No puede, ya que no le da la oportunidad de especificar cómo se ven sus models antes de crear el proyecto. Todo lo que sabe es que va a tener una vista, por lo que crea esa vista para usted (en un file .xib) y un controller para esa vista (en los files .h y .m).

El file .xib recibe el nombre del controller. Siempre encontré esto confuso, pero esa es una decisión que tomó Apple.

Puede simular la creación del model en XCode ingresando al editor de datos básicos y creando un nuevo model de datos básicos (Archivo -> Nuevo -> Archivo -> Datos básicos -> Modelo de datos). Cuando complete este model, puede crear files que describan los nuevos objects de model seleccionando las entidades que ha creado yendo a Editor -> Crear subclass NSManagedObject; esto generará files .h y .m que envuelven los objects del model que ha descrito.

Por supuesto, los objects de su model no tienen que estar respaldados por una tienda persistente; puede crear nuevos files para ellos sin tener que ir a la ruta Core Data. Pero XCode no aplica la estructura de directorys que hace Rails. Felizmente agrupará todos sus files MVC juntos en el mismo directory. Depende de usted crear esa estructura si lo desea.

¿xib es una vista? pero tiene un controller de visión en su nombre que me retuerce un poco.

Sí, estoy de acuerdo, esto es confuso. XCode nombra los files de vista (.xibs) después de sus objects de controller. No creo que sea un gran enfoque, pero ahí lo tienes.

En resumen: XCode creará automáticamente files de vista y controller cada vez que agregue un nuevo file de vista a sus proyectos. Nunca (por lo que yo sé) crea un file model para usted explícitamente, excepto cuando usa el editor Core Data, e incluso entonces no pone "model" en el nombre del file; simplemente nombra el file después de la entidad que tu creaste

No se confunda con la "vista" en "controller de vista".

Por lo general, es su "controller". Si usas files xib o storyboards, normalmente serían tu "vista".

Los models, para una separación clara, deben estar en files separados; sin embargo, en muchos tutoriales, el model se representará mediante código en el "controller de vista" y típicamente será un almacén de datos formado por una matriz o dictionary.

El área que te confundirá cuando aprendas es cuando encuentras el código de "vista", en realidad en código. Por lo general, puede identificar esto cuando ve un código como [self.view addSubView: someOtherView] junto con un montón de código que crea elementos de interfaz de usuario y establece sus frameworks y máscaras, etc.

No dejes que eso te confunda. Probablemente deberían estar en files separados también, pero a menudo no están mezclados. Aunque está en el "controller de visualización", realmente es la "V" en MVC.

En algunos ejemplos recuerdo haber leído, no lo supe en ese momento, pero luego me di count de que habían representado a todo el MVC en un solo controller de vista. Esto es bastante posible, aunque obviamente no se recomienda.

Otras cosas que pueden ser confusas: las properties de class pueden servir como models. Una matriz de 25 fotos, por ejemplo. Puede encontrar ejemplos que muestren el código para hacer la connection de networking y la recuperación de las fotos en el lado del "controller de vista", sin embargo, este es realmente el código "M". Una vez que se recuperan y almacenan las fotos, el titular de esos datos se convierte en el model. La forma correcta sería diseñar una class para ejecutar la llamada de networking y devolver las fotos al controller (controller de visualización) y luego llamar a un método que actualice la UI (vista) con los nuevos datos. Con frecuencia, esto se mezcla en el controller de vista y puede ver algo así como una llamada de networking que proporciona un bloque de finalización y en el bloque de finalización, las properties de la vista se actualizan. En pequeñas "escenas" donde esa llamada de networking es la única llamada para incorporar datos de model, entonces tal vez sea realmente más simple y más eficiente tener esa instrucción de bloque único en el controller (controller de vista). Sin embargo, si se hacen muchas llamadas para recuperar datos, entonces debería aislarse en su propio file de class y ser una "M".

en la mayoría de las aplicaciones IOS, obtienes un nuevo MVC para cada "escena" o nueva vista que se presenta. Realmente no tienes un controller, sino muchos. En mis propias palabras, también diría que tiene el concepto de "controlleres de controlleres" en una aplicación iOS. Ejemplos de estos serían la aplicaciónDelegate, controlleres de navigation, controlleres de barra de tabulación, controller de vista dividida. Es posible que también tenga un controller model, como Core Data, por ejemplo, un gran controller que controle muchos objects model a través de su context. Y el guión gráfico, si lo piensas bien, es realmente un controller de vistas. En estos casos, arranca los controlleres, vistas y objects de model específicos que necesita para cada escena y los conecta.

Espera que ayude y no cause más confusión. cuidate.