Я следую парадигме 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. Я проверил почти что возможно. Не знаю, что делать. Я застрял.
Где это крах именно? Что такое описание исключения? Почему он сам -> _ subTitle не self.subTitle? –
subTitle - свойство, которое имеет атрибут readonly. Поэтому я решил использовать указатель объекта – rahulbsb
Как показать консольный журнал. это слишком долго. Текстовое поле жалуется. Вы знаете об обходном пути. – rahulbsb