
Модели помогают структурировать данные. В базовом приложении есть вью, которые отображают данные и контроллеры, которые говорят вью, как отображать данные моделей.
Модели - это будут наши класы, которые будут описывать наши данные (наши объекты).
Все модели наследуем от NSObject. При создании новой модели Xcode создаст базовые файлы файлы
#import <Foundation/Foundation.h>
@interface Place: NSObject
@end
#import "Place.h"
@implementation Place
@end
Как обычно, создаем свойста.
Переопределяем метод иницыализации.
-(id)init
{
self = [super init];
return self;
}
Следует так же применять практику задавать свойства при инцыализации экземпляра, т.е нужно написать метод иницыализации, которыд будет принимать параметры в качестве свойств.
В общем методе "init" так же не плохо задавать дефолтные значения свойств.
Существуют некоторые рекомандации:
//свойства создаем с параметрами "strong, nonatomic"
@property (strong, nonatomic) NSString *name;
//имена экземпляров начинаем с артикля
Place *aPlace = [[Place aloc] init];
//а длинные методы разбиваем на строки по одной для каждого аргумента
Для использования данных в контроллере, в коде контроллера пользуемся экземпляром модели:
//PlaceViewController.h
@property (strong, nonatomic) Place *aPlace;
//PlaceViewController.m
- (void)viewDidLoad {
Place *aPlace = [[Place alloc] init];
}
Получаем данные из JSON
Желательно это запихнуть в иницыализатор модели, а не во вью-контроллер.
NSURL *url = [[NSURL alloc] initWithString:@"http://codeschool.com/cityData.json"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.city = [[City alloc] init];
self.city.name = JSON[@"name"];
self.city.state = JSON[@"state"];
[self dataRetrieved];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(@"NSError: %@",error.localizedDescription);
}];
[operation start];
Но! Запрос выполняется асинхронно, поэтому нам нужны Notifications. Они общаются с NSNotificationCenter
//Sending a Notification (пишем внутри AJAX в файле модели)
[[NSNotificationCenter defaultCenter]
postNotificationName:@"initWithJSONFinishedLoading"
object:nil];
//Listening for a Notification (пишем во вью-контроллере)
//по завершению AJAX будет вызван метод "dataRetrieved"
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(dataRetrieved)
name:@"initWithJSONFinishedLoading"
object:nil];
Другие операции
В случае, когда нам нужно добавить элементы в массив методом addObject:newObject, нам нужен Mutable Class - NSMutableArray вместо Immutable (NSArray), элементы которого после создания изменять нельзя.
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:newPlace];
Следует заметить, что для обращения к свойствам часто необходимо использовать синтаксис сообщений, а не точки. В примере свойство "name" мы можем получить только так:
cell.textLabel.text = [self.places[indexPath.row] name];
Строим View
Создаем tableView (список)
//подсчитываем количество рядков
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return self.places.count;
}
//создаем рядок
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"pCell"];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"pCell"];
}
cell.textLabel.text = [self.places[indexPath.row] name];
return cell;
}
//действие при выборе рядка
- (void) tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PlaceViewController *placeVC = [PlaceViewController alloc] init];
placeVC.place = self.places[indexPath.row];
[self.navigationController pushViewController:placeVC animated:YES];
}
Размещаем данные во вью:
//PlaceViewController.h
#import "Place.h"
@interface PlaceViewController : UIViewController
@property (strong, nonatomic) Place *place;
@property (strong, nonatomic) UILabel *placeNameLabel;
@property (strong, nonatomic) UILabel *placeDescriptionLabel;
//PlaceViewController.m
- (void)viewDidLoad {
self.placeNameLabel = [[UILabel alloc] init];
self.placeNameLabel.frame = CGRectMake(20,40,280,40);
[self.view addSubview:self.placeNameLabel];
self.placeDescriptionLabel = [[UILabel alloc] init];
self.placeDescriptionLabel.frame = CGRectMake(20,100,280,20);
[self.view addSubview:self.placeDescriptionLabel];
}
- (void)viewWillAppear:(BOOL)animated {
self.placeNameLabel.text = self.place.name;
self.placeDescriptionLabel.text = self.place.description;
}
Инпуты
В моделях создаем переменные, которые будут хранитиь данные. В контроллере создаем инпут и его лейбл:
//CityViewController.h
//Добавляем протокол "UITextFieldDelegate"
@interface CityViewController : UIViewController <UITextFieldDelegate>
@property (strong, nonatomic) City *city;
@property (strong, nonatomic) UILabel *notesLabel;
@property (strong, nonatomic) UITextField *notesField;
//CityViewController.m
- (void)viewDidLoad {
self.notesLabel = [[UILabel alloc] init];
self.notesLabel.frame = CGRectMake(20,160,280,40);
//назначаем стиль клавиатуры
self.notesField.keyboardType = UIKeyboardTypeDefault;
//назначаем стиль border
self.notesField.borderStyle = UITextBorderStyleRoundedRect;
//связываем инпут с нашим контроллером
self.notesField.delegate = self;
}
Получаем данные с инпута:
//CityViewController.m
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
//получаем значение с инпута
self.city.notes = self.notesField.text;
//прячем клавиатуру
[textField resignFirstResponder];
return YES;
}