середа, 23 травня 2012 р.

@Objective-C (middle level) @"Core Data and UITextField"

Привіт усім, сьогодні хочу поділитись своїми доробками в напрямку згаданому в заголовку.
Наперед маю сказати, що для мене Core Data довго залишалася технологія, яка виносить мозок. Вона виїдала його ніби американські підлітки (жіночої статі), які гризуть здоровенними ложками морозиво в моменти коли їм страшно чи їх кинув їхній бойфренд. От і я відчував присутність такої ложки в своїй голові, в ті моменти коли сідав за ознайомлення з Core Data. І все ніби зрозуміло, дивишся уроки читаєш блоги, все ясно. Та відчуваєш всерівно себе, як той собака з бородатої історії, що все розумів мав розумні очі тільки сказати нічого не може, в моєму випадку написати код. Проте з'явився стимул так би мовивти каталізатор, поштовх, можна це називати, як завгодно адже завдання на роботі для кожного сприймається по своєму. Після цього прийшлось робити бліцкриг на дану технологію, результат якої ви зараз читаєте.
Питання вирішилось доволі швидко, адже з таким каталізатором все робиться швидше. Що б конкретно хотілось сказати по цій технології:
* CORE DATA  ЦЕ НАДБУДОВА НАД SQLITE - і не дивуйтесь чого я так виділив просто не розуміння цього мене, як виявилося в кінці дуже-дуже затормозило і ввело в оману.
* NSPredicate - почитайте це корисна річ.
* І в загальному, часом треба просто знайти правильний урок.
На перед забігаючи маю сказати, що код містить відверті частини копіпасту, який я виділю.
По скріншоту доречі можна зрозуміти, що я застосував storyboard з iOS 5.

Отже, розпочнемо:

CoreAppDelegate.h


#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface CoreAppDelegate : UIResponder <UIApplicationDelegate>

@property (retain, nonatomic) UIWindow *window;
@property (nonatomic, retain) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, retain) NSManagedObjectModel        * managedObjectModel;
@property (nonatomic, retain) NSPersistentStoreCoordinator * persistentStoreCoordinator;
@end
Повідомляємо про властивості нашого класу.

#import "CoreAppDelegate.h"
#import "CoreViewController.h"

@implementation CoreAppDelegate

@synthesize window = _window;
@synthesize managedObjectContext = _managedObjectContext;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize managedObjectModel = _managedObjectModel;

- (void)dealloc
{
  [_window release];
  self.managedObjectContext = nil;
  self.persistentStoreCoordinator = nil;
  self.managedObjectModel = nil;
  [super dealloc];
}

Взятий код з інтернету з відповідними поясненнями на мові Шекспіра.(Copy paste source from internet)
/*===========================*/
#pragma mark -
#pragma mark Core Data stack

/**
 Returns the managed object context for the application.
 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
 */
- (NSManagedObjectContext *) managedObjectContext {
  if (_managedObjectContext != nil) {
    return _managedObjectContext;
  }
  NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
  if (coordinator != nil) {
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator: coordinator];
  }
  return _managedObjectContext;
}


/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
 */
- (NSManagedObjectModel *)managedObjectModel {
  if (_managedObjectModel != nil) {
    return _managedObjectModel;
  }
 NSManagedObjectModel* object =  [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
  _managedObjectModel = object;
  return _managedObjectModel;
}


/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
  if (_persistentStoreCoordinator != nil) {
    return _persistentStoreCoordinator;
  }
//Довгий період часу - НАСТУПНА СТРІЧКА КОДУ мене збивала з пантелику, придивіться уважно, SQLITE!!!(Core Data - надбудова над SQLITE)
  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"StudentDB.sqlite"]];
NSError *error = nil;
  _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
  if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
 
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
 
Typical reasons for an error here include:
* The persistent store is not accessible
* The schema for the persistent store is incompatible with current managed object model
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
  }    
  return _persistentStoreCoordinator;
}


#pragma mark -
#pragma mark Application's Documents directory

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
//Я тут змінив місце знаходження файлу бази по причині того, що з версії iOS 5.0 з'явилась можливість роботи з iCloud тому зберігати в NSDocuments тепер треба специфічно (детальніше курим доку).
return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
}

@end

CoreViewController.h
#import <UIKit/UIKit.h>
@interface CoreViewController : UIViewController
@end

CoreViewController.m
#import "CoreViewController.h"
#import "CoreAppDelegate.h"
#import "Student.h"

@interface CoreViewController ()<UITextFieldDelegate>
//Налаштування textField можна подивитись у відповідному xib файлі
@property (retain, nonatomic) IBOutlet UITextField *firstNameField;
@property (retain, nonatomic) IBOutlet UITextField *lastNameField;
@property (retain, nonatomic) IBOutlet UITextField *ageField;
//Додаємо в колекцію всі поля щоб легше з ними було працювати
@property (retain, nonatomic) IBOutletCollection(UITextField) NSArray *fieldsCollection;
//Об'єкт для зв'язку з нашою базою
@property (nonatomic, retain) NSManagedObjectContext * context;
@end

@implementation CoreViewController
@synthesize firstNameField = _firstNameField;
@synthesize lastNameField = _lastNameField;
@synthesize ageField = _ageField;
@synthesize fieldsCollection = _fieldsCollection;
@synthesize context = _context;



- (void)viewDidLoad
{
    [super viewDidLoad];

//====Зв'язок з базою=====/
    CoreAppDelegate * appDelegate = [[UIApplication sharedApplicationdelegate];
    self.context = [appDelegate managedObjectContext];
  // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [self setFirstNameField:nil];
    [self setLastNameField:nil];
    [self setAgeField:nil];
    [self setFieldsCollection:nil];
    self.context = nil;
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}




//====При натисненні на кнопку save(її реалізації немає, як проперті, нам цього і не треба в даному прикладі)=====//
- (IBAction)saveStudentInfo:(id)sender {
//=====Створення екземпляру з занесенням даних в нього=====//
    Student * student =  [NSEntityDescription                                                            insertNewObjectForEntityForName:@"Student"                                                            inManagedObjectContext:_context];
    student.firstName = _firstNameField.text;
    student.lastName  = _lastNameField.text;
    student.age       =  [NSNumber numberWithInteger:[_ageField.text integerValue]];  
    NSError * error;
//=====Спроба зберегти=====//
    if (![_context save:&error]) 
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
 //===Онуляємо значення полів   
    [_fieldsCollection makeObjectsPerformSelector:@selector(setText:) withObject:@""];
  NSLog(@"%s", __PRETTY_FUNCTION__);
}
    
- (void)dealloc {
    [_firstNameField release];
    [_lastNameField release];
    [_ageField release];
    [_fieldsCollection release];
    [super dealloc];
}
@end



#import "SchoolStudentsTabelListViewController.h"
#import "CoreAppDelegate.h"
#import "Student.h"

@interface SchoolStudentsTabelListViewController ()
@property (nonatomic, retain)NSManagedObjectContext * context;
//Список студентів взятих з бази
@property (nonatomic, retain)NSArray * students;


@end

@implementation SchoolStudentsTabelListViewController
@synthesize context = _context;
@synthesize students = _students;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
//Зв"язок з базою
    CoreAppDelegate * appDelegate = [[UIApplication sharedApplication] delegate];
    self.context = [appDelegate managedObjectContext];
    self.entityDescription = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:_context];
    _selected = NO;
    [self studentsList];
    
}

- (void)viewDidUnload
{
  [super viewDidUnload];
  self.context = nil;
  self.students = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//{
//#warning Potentially incomplete method implementation.
//    // Return the number of sections.
//    return 0;
//}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [_students count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Student Data";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
// Вивід данних в таблиці
  Student * student = [_students objectAtIndex:indexPath.row];
  cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", student.firstName, student.lastName];
  cell.detailTextLabel.text = [student.age description];
    // Configure the cell...
    
    return cell;
}
//Вибираємо список необхідних нам учнів

-(void) studentsList
{
    NSFetchRequest * request = [[NSFetchRequest alloc] init];
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"(age BETWEEN {10, 50})"];/* OR (firstName LIKE[c] 'Max')"];*/
    
    [request setEntity:_entityDescription];
    [request setPredicate:predicate];
    NSError * error;
    self.students = [_context executeFetchRequest:request error:&error];
    if (_students == nil)
        NSLog(@"The error with Core Data");
    NSLog(@"Number of elements %d", [_students count]);
    [request release];
}

//Метод, який фіксує, що хоча б раз було виділено строку

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    _selected = YES;
}



//Видаляємо вибраний рядок

- (IBAction)deleteChoosenRow:(UIBarButtonItem *)sender
{
    if (_selected && ([_students count ] > 0))
    {
        NSInteger row = [self.tableView indexPathForSelectedRow].row;
        
        Student * student = [_students objectAtIndex:row];
        [_context deleteObject:student];
        
        NSError * error;
        if (![_context save:&error])
        {
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
            return;
        }
        [self studentsList];
        [self.tableView reloadData];
        NSLog(@" %d num", [_students count]);
    }
}
@end



Стаття в процесі написання.
Source at: https://github.com/Samback/MicroBlogerStories/tree/core_data_example

Немає коментарів:

Дописати коментар