2014-01-17 3 views
0

Я следую парадигме MVCS для сохранения и последующей загрузки экземпляров объектов данных в тестовом приложении, связанном с обновлением данных сопоставления.Архивирование и Развертывание данных/объектов модели

BNRMapPoint.h

#import <Foundation/Foundation.h> 
#import <MapKit/MapKit.h> 
#import <CoreLocation/CoreLocation.h> 
@interface BNRMapPoint : NSObject<MKAnnotation, NSCoding> 
{ 
    double latitude; 
    double longitude; 
    @public NSArray *mapPoints; 
} 
-(id) initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t subTitle:(NSString *)st; 

//this is required property in MKAnnotation Protocol 
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 

//this is an optional property in MKAnnotation Protocol 
@property (nonatomic, copy) NSString *title; 
//this is an optional property in MKAnnotation Protocol 
@property (nonatomic,readonly,copy) NSString *subTitle; 
@end 

BNRMapPoint.m (модель)

#import "BNRMapPoint.h" 

@implementation BNRMapPoint 
@synthesize coordinate=_coordinate; 
@synthesize title=_title; 
@synthesize subtitle=_subtitle; 

-(void)encodeWithCoder:(NSCoder *)aCoder{ 
    latitude = self.coordinate.latitude; 
    longitude = self.coordinate.longitude; 

    [aCoder encodeObject:self.title forKey:@"title"]; 
    [aCoder encodeObject:_subTitle forKey:@"subTitle"]; 
    [aCoder encodeDouble: latitude forKey:@"latitude"]; 
    [aCoder encodeDouble:longitude forKey:@"longitude"]; 
} 
-(id)initWithCoder:(NSCoder *)aDecoder{ 
    if (self= [super init]) { 
     [self setTitle:[aDecoder decodeObjectForKey:@"title"]]; 
     self->_subTitle= [aDecoder decodeObjectForKey:@"subTitle"]; 
     latitude= [aDecoder decodeDoubleForKey:@"latitude"]; 
     longitude= [aDecoder decodeDoubleForKey:@"longitude"]; 
    } 
    return self; 
} 

-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t subTitle:(NSString *)st{ 
    if (self= [super init]) { 
    self.coordinate=c; 
    self.title=t; 
    _subtitle=st; 
    } 
    return self; 
} 
    -(id) init{ 
    return [self initWithCoordinate:CLLocationCoordinate2DMake(43.07, -89.32) title:@"Hometown" subTitle:self.subtitle]; 
} 

@end 

WhereamiViewController.h

#import <UIKit/UIKit.h> 
    #import <CoreLocation/CoreLocation.h> 
    #import <MapKit/MapKit.h> 
    #import "BNRMapPoint.h" 
    #import "RootObject.h" 
    @interface WhereamiViewController :  UIViewController<CLLocationManagerDelegate,MKMapViewDelegate,UITextFieldDelegate> 
    { 
     @public RootObject *rootObj; 
     CLLocationManager *locationManager; 

     IBOutlet MKMapView *worldView; 
     IBOutlet UIActivityIndicatorView *activityIndicator; 
     IBOutlet UITextField *locationTitleField; 
    } 
    -(IBAction)buttonDidGetPressed:(id)sender; 
    -(BOOL)textFieldShouldReturn:(UITextField *)textField; 
    -(void)findLocation; 
    -(void)foundLocation:(CLLocation *)loc; 

    @end 

WhereamiViewController.m (ViewController)

#import "WhereamiViewController.h" 

    @interface WhereamiViewController() 

    @end 

    @implementation WhereamiViewController 

    -(IBAction)buttonDidGetPressed:(UISegmentedControl *)sender{//Silver challenge 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 
     if([sender selectedSegmentIndex]==0){ 
      [worldView setMapType:MKMapTypeStandard]; 
     } 
     else if([sender selectedSegmentIndex]==1){ 
      [worldView setMapType:MKMapTypeHybrid]; 
     } 
     else if([sender selectedSegmentIndex]==2){ 
      [worldView setMapType:MKMapTypeSatellite]; 
     } 
    } 
     -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ 
      NSLog(@"%@", NSStringFromSelector(_cmd)); 
     if (self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 
      rootObj= [[RootObject alloc] init]; 
      locationManager= [[CLLocationManager alloc] init]; 

      [locationManager setDelegate:self];//self is Whereamicontroller. The delegate pointer is of type id<CLLocationManagerDelegate> and is an ivar of CLLocationManager. 
      [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];  
      } 
      NSLog(@"test"); 
     return self; 
     } 

     -(void) viewDidLoad{ 
      // [worldView setMapType:MKMapTypeSatellite]; Bronze challenge 
      [worldView setShowsUserLocation:YES]; 
     } 
     -(void)findLocation{ 
      NSLog(@"%@",NSStringFromSelector(_cmd)); 
      [locationManager startUpdatingLocation];//This calls locationManager:didUpdateLocations: 
      NSLog(@"location updated"); 
      [activityIndicator startAnimating]; 
      [locationTitleField setHidden:YES]; 
     } 
     -(BOOL)textFieldShouldReturn:(UITextField *)textField{ 
      NSLog(@"%@",NSStringFromSelector(_cmd)); 
      [self findLocation]; 
      [textField resignFirstResponder]; 
      return YES; 
     } 

     -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{ 
      NSLog(@"%@",NSStringFromSelector(_cmd)); 
      CLLocationCoordinate2D centerCoordinate= [[userLocation location] coordinate]; //get the coordinate of current location. 
      MKCoordinateSpan span= MKCoordinateSpanMake(250, 250);//Structure members 
      MKCoordinateRegion mapPortionToDisplay= MKCoordinateRegionMakeWithDistance(centerCoordinate, span.latitudeDelta, span.longitudeDelta);//span.latitudeDelta=250 and span.longitudeDelta=250 
      [worldView setRegion:mapPortionToDisplay animated:YES]; 
      // [worldView setRegion:mapPortionToDisplay]; 
     } 

     -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{ 
      NSLog(@"%@",NSStringFromSelector(_cmd)); 
      NSLog(@"Heading %@",newHeading); 
     } 
     -(void)foundLocation:(CLLocation *)loc{ 
      NSLog(@"%@",NSStringFromSelector(_cmd)); 
      CLLocationCoordinate2D coord= [loc coordinate]; 

      NSDateFormatter *formatter= [[NSDateFormatter alloc] init]; 

      NSDate *currentDate= [[NSDate alloc] init]; 
      [formatter setDefaultDate:currentDate]; 

      BNRMapPoint *bmp= [[BNRMapPoint alloc] initWithCoordinate:coord title:[locationTitleField text] subTitle:[[formatter defaultDate] description]]; 
      [rootObj.mapPoints addObject:bmp]; 

      [worldView addAnnotation:bmp]; 

      MKCoordinateRegion region= MKCoordinateRegionMakeWithDistance(coord,250,250); 
      [worldView setRegion:region animated:YES]; 

       //RESET the UI 
      [locationTitleField setText:@" "]; 
      [activityIndicator stopAnimating]; 
      [locationTitleField setHidden:NO]; 
       [locationManager stopUpdatingLocation]; 
     } 
     -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ //CLLocationManagerDelegate method implementation 

      NSLog(@"%@", NSStringFromSelector(_cmd)); 
     // NSTimeInterval t0=[[locations lastObject] timeIntervalSinceNow]; 

      NSLog(@"%@",(CLLocation *)[locations lastObject]); 
      NSTimeInterval t= [[(CLLocation *)[locations lastObject] timestamp] timeIntervalSinceNow]; 

      if (t<-180) { 
      return; //No op 
      } 

      [self foundLocation:[locations lastObject]]; 

     } 

     -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ 
      NSLog(@"Could not find location: %@",error);//CLLocationManagerDelegate method implementation 
     } 


     @end 

RootObject.h

 #import <Foundation/Foundation.h> 

     @interface RootObject : NSObject 
     @property NSMutableArray *mapPoints; 
     -(BOOL)saveChanges; 
     -(NSString *)dataObjectArchivePath; 
     @end 

RootObject.m (магазин)

 #import "RootObject.h" 

     @implementation RootObject 
     @synthesize mapPoints; 

    -(NSString *)dataObjectArchivePath{ 
     NSArray *documentDirectories= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentDirectory= [documentDirectories objectAtIndex:0]; 

      NSString *finalPath= [documentDirectory stringByAppendingPathComponent:@"items.archive"]; 
     return finalPath; 
     } 
     -(BOOL)saveChanges{ 
      NSString *path= [self dataObjectArchivePath]; 
      return [NSKeyedArchiver archiveRootObject:self.mapPoints toFile:path];writing to the file items.archive 
     } 
     -(id)init{ 
      if (self=[super init]) { 
      NSString *path= [self dataObjectArchivePath]; 
      self.mapPoints= [NSKeyedUnarchiver unarchiveObjectWithFile:path];//reading from the file items.archive 

      if (!self.mapPoints) { 
       self.mapPoints= [[NSMutableArray alloc] init]; 
     } 
     } 
     return self; 
    } 
    @end 

AppDelegate.m

 - (void)applicationDidEnterBackground:(UIApplication *)application 
     { 
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 
     BOOL success= [[BNRItemStore sharedStore] saveChanges]; 
     if (success) { 
      NSLog(@"Saved all of the BNRItems"); 
     } 
     else{ 
     NSLog(@"Could not save any of the BNRItems"); 
     } 
    } 

В приведенном выше коде, метод SaveChanges вызывается из приложения: didEnterBackground :. Поэтому я не создал объект Singleton для Store (RootObject). Но я создал его в назначенном инициализаторе viewController. Данные для архивирования - это объекты BNRMapPoint. При входе в фоновое состояние код успешно сохранил объекты. Однако после перезагрузки приложения initWithCoder - это место, где он застревает. Приложение падает, когда дело доходит до чтения ранее сохраненных объектов MapPoint. Помощь Pls. Я проверил почти что возможно. Не знаю, что делать. Я застрял.

+0

Где это крах именно? Что такое описание исключения? Почему он сам -> _ subTitle не self.subTitle? –

+0

subTitle - свойство, которое имеет атрибут readonly. Поэтому я решил использовать указатель объекта – rahulbsb

+0

Как показать консольный журнал. это слишком долго. Текстовое поле жалуется. Вы знаете об обходном пути. – rahulbsb

ответ

0

Таким образом, проблема в том, что у вас есть:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 

И вы пытаетесь использовать сеттер на только для чтения собственности:

self.coordinate=c; 

Вот почему он говорит, что непризнанные селектор отправить - becuase это правильно, поэтому сеттер не существует. Используя свойство это было одно и то же, как вызов:

[self setCoordinate:c] 

Просто сделайте свойство назначаемого

+0

О да .. мой плохой. Как я этого не видел ... Как глупо со мной. Так что, если я держу его только для чтения, должен ли я напрямую использовать указатель объекта ?? Какой подход лучше? – rahulbsb

+0

Должен ли он дать мне ошибку времени компиляции, когда я использовал self.coordinate, пока он только для чтения?Я думаю, что это не было – rahulbsb

+0

еще один горящий вопрос. После перезапуска приложения не следует ссылаться на ссылку NSMutableArray в методе init, возвращающий исходный адрес памяти, где объект массива из предыдущего запуска хранит MapPoints. Во время выполнения кода второй раз мы повторно инициализируем указатель mapPoints объекта, тем самым указывая на совершенно новый объект NSMutableArray в совершенно новом месте памяти, в котором нет необходимости иметь ранее сохраненные объекты данных. – rahulbsb

Смежные вопросы