2015-04-07 74 views
0

好吧,所以即時製作一個全球定位系統跟蹤應用程序,跟蹤用戶的所有代碼工作良好,但現在即時通訊嘗試傳遞數據保存並顯示在彙總視圖。我有一個在模型中正確設置的實體Run,我意識到我需要使用options方法向appDelegate.m didFinishLaunching添加一些內容,以便managedObjectContext被正確初始化,但我似乎無法弄清楚。任何幫助將被大力讚賞。核心數據,enitityForName零誤差

這裏是我的錯誤

終止應用程序由於未捕獲的異常 「NSInvalidArgumentException」的,理由是:「+ entityForName:無不是 法律的NSManagedObjectContext參數搜索實體名稱 ‘運行’」

這裏是我的應用程序delegate.m

'import "AppDelegate.h" 
#import <CoreData/CoreData.h> 
#import "SummaryViewController.h" 
#import "CardioViewController.h" 

@interface AppDelegate() 

@end 

@implementation AppDelegate 

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


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 


     return YES; 
} 


- (void)saveContext 
{ 
    NSError *error = nil; 
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 
    if (managedObjectContext != nil) { 
     if ([managedObjectContext hasChanges] && ![managedObjectContext save:&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. 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
    } 
} 


#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 from the application's model. 
- (NSManagedObjectModel *)managedObjectModel 
{ 
    if (_managedObjectModel != nil) { 
     return _managedObjectModel; 
    } 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Beginner Fitness" withExtension:@"momd"]; 
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    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; 
    } 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Beginner Fitness.sqlite"]; 

    NSError *error = nil; 
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return _persistentStoreCoordinator; 
} 

#pragma mark - Application's Documents directory 

// Returns the URL to the application's Documents directory. 
- (NSURL *)applicationDocumentsDirectory 
{ 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
} 

@end' 

這裏是我的CardioViewController,我使用了斷點,錯誤發生在第一次提到「Run」時saveRun方法的開始處,正如您對錯誤的期望。

static NSString * const detailSegueName = @"NewRunDetails"; 


@interface CardioViewController()<UIActionSheetDelegate, CLLocationManagerDelegate, MKMapViewDelegate> 

@property int seconds; 
@property float distance; 
@property (nonatomic, strong) CLLocationManager *locationManager; 
@property (nonatomic, strong) NSMutableArray *locations; 
@property (nonatomic, strong) NSTimer *timer; 
@property (nonatomic, strong) Run *run; 


@property (nonatomic, weak) IBOutlet UILabel *timeLabel; 
@property (nonatomic, weak) IBOutlet UILabel *distLabel; 
@property (nonatomic, weak) IBOutlet UILabel *paceLabel; 
@property (nonatomic, weak) IBOutlet UIImageView *progressImageView; 
@property (nonatomic, weak) IBOutlet UIButton *startButton; 
@property (nonatomic, weak) IBOutlet UIButton *stopButton; 
@property (nonatomic, weak) IBOutlet MKMapView *mapView; 

@end 


@implementation CardioViewController{ 
    NSMutableArray *locationsArray; 
} 
@synthesize mapView = _mapView; 



- (void) viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    self.navigationItem.title = _DetailModal2[0]; 
} 

- (void) viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
    [self.timer invalidate]; 
} 

#pragma mark - IBActions 

-(IBAction)startPressed:(id)sender 
{ 
    // hide the start UI 

    // show the running UI 
    self.seconds = 0; 

    // initialize the timer 
    self.timer = [NSTimer scheduledTimerWithTimeInterval:(1.0) target:self selector:@selector(eachSecond) userInfo:nil repeats:YES]; 

    self.distance = 0; 
    self.locations = [NSMutableArray array]; 

    [self startLocationUpdates]; 
} 

- (IBAction)stopPressed:(id)sender 
{ 
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Save", @"Discard", nil]; 
    actionSheet.actionSheetStyle = UIActionSheetStyleDefault; 

    [actionSheet showInView:self.view]; 
} 


#pragma mark - Private 


- (void)saveRun 
{ 

    Run *newRun = [NSEntityDescription insertNewObjectForEntityForName:@"Run" inManagedObjectContext:self.managedObjectContext]; 

    newRun.distance = [NSNumber numberWithFloat:self.distance]; 
    newRun.duration = [NSNumber numberWithInt:self.seconds]; 
    newRun.timestamp = [NSDate date]; 

    NSMutableArray *locationArray = [NSMutableArray array]; 
    for (CLLocation *location in self.locations) { 
     Location *locationObject = [NSEntityDescription insertNewObjectForEntityForName:@"Location" inManagedObjectContext:self.managedObjectContext]; 

     locationObject.timestamp = location.timestamp; 
     locationObject.latitude = [NSNumber numberWithDouble:location.coordinate.latitude]; 
     locationObject.longitude = [NSNumber numberWithDouble:location.coordinate.longitude]; 
     [locationArray addObject:locationObject]; 
    } 

    newRun.locations = [NSOrderedSet orderedSetWithArray:locationArray]; 
    self.run = newRun; 

    // Save the context. 
    NSError *error = nil; 
    if (![self.managedObjectContext save:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 


} 


- (void)eachSecond 
{ 
    self.seconds++; 
    [self updateProgressImageView]; 
    [self updateLabels]; 
} 

- (void)updateProgressImageView 
{ 
    int currentPosition = self.progressImageView.frame.origin.x; 
    CGRect newRect = self.progressImageView.frame; 

    switch (currentPosition) { 
     case 20: 
      newRect.origin.x = 80; 
      break; 
     case 80: 
      newRect.origin.x = 140; 
      break; 
     default: 
      newRect.origin.x = 20; 
      break; 
    } 

    self.progressImageView.frame = newRect; 
} 

- (void)updateLabels 
{ 
    self.timeLabel.text = [NSString stringWithFormat:@"Time: %@", [MathController stringifySecondCount:self.seconds usingLongFormat:NO]]; 
    self.distLabel.text = [NSString stringWithFormat:@"Distance: %@", [MathController stringifyDistance:self.distance]]; 
    self.paceLabel.text = [NSString stringWithFormat:@"Pace: %@", [MathController stringifyAvgPaceFromDist:self.distance overTime:self.seconds]]; 

} 

- (void)startLocationUpdates 
{ 
    // Create the location manager if this object does not 
    // already have one. 
    if (self.locationManager == nil) { 
     self.locationManager = [[CLLocationManager alloc] init]; 
    } 

    self.locationManager.delegate = self; 
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
    self.locationManager.activityType = CLActivityTypeFitness; 

    // Movement threshold for new events. 
    self.locationManager.distanceFilter = 10; // meters 

    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 
     [self.locationManager requestWhenInUseAuthorization]; 
    } 
    [self.locationManager startUpdatingLocation]; 
} 

#pragma mark - UIActionSheetDelegate 

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
    [self.locationManager stopUpdatingLocation]; 
    // save 
    if (buttonIndex == 0) { 

     [self saveRun]; 
     [self performSegueWithIdentifier:detailSegueName sender:nil]; 
     // discard 
    } else if (buttonIndex == 1) { 
     [self.navigationController popToRootViewControllerAnimated:YES]; 
    } 
} 

#pragma mark - CLLocationManagerDelegate 

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateLocations:(NSArray *)locations 
{ 
    for (CLLocation *newLocation in locations) { 

     NSDate *eventDate = newLocation.timestamp; 

     NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; 

     if (fabs(howRecent) < 10.0 && newLocation.horizontalAccuracy < 20) { 

      // update distance 
      if (self.locations.count > 0) { 
       self.distance += [newLocation distanceFromLocation:self.locations.lastObject]; 

       CLLocationCoordinate2D coords[2]; 
       coords[0] = ((CLLocation *)self.locations.lastObject).coordinate; 
       coords[1] = newLocation.coordinate; 

       MKCoordinateRegion region = 
       MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 500, 500); 
       [self.mapView setRegion:region animated:YES]; 

       [self.mapView addOverlay:[MKPolyline polylineWithCoordinates:coords count:2]]; 
      } 

      [self.locations addObject:newLocation]; 
     } 
    } 
} 

#pragma mark - MKMapViewDelegate 

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay 
{ 
    if ([overlay isKindOfClass:[MKPolyline class]]) { 
     MKPolyline *polyLine = (MKPolyline *)overlay; 
     MKPolylineRenderer *aRenderer = [[MKPolylineRenderer alloc] initWithPolyline:polyLine]; 
     aRenderer.strokeColor = [UIColor blueColor]; 
     aRenderer.lineWidth = 3; 
     return aRenderer; 
    } 

    return nil; 
} 

- (void)dealloc 
{ 
    // 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 

     self.locationManager.delegate = nil; 
} 

- (void)initilizeLocationTracking 
{ 
    _locationManager = [[CLLocationManager alloc] init]; 
    assert(self.locationManager); 

    self.locationManager.delegate = self; // tells the location manager to send updates to this object 
     // 
    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) 
    { 
     [self.locationManager requestWhenInUseAuthorization]; 
    } 

    // start tracking the user's location 
    [self.locationManager startUpdatingLocation]; 

    } 


- (MKCoordinateRegion)coordinateRegionWithCenter:(CLLocationCoordinate2D)centerCoordinate approximateRadiusInMeters:(CLLocationDistance)radiusInMeters 
{ 
    // Multiplying by MKMapPointsPerMeterAtLatitude at the center is only approximate, since latitude isn't fixed 
    // 
    double radiusInMapPoints = radiusInMeters*MKMapPointsPerMeterAtLatitude(centerCoordinate.latitude); 
    MKMapSize radiusSquared = {radiusInMapPoints,radiusInMapPoints}; 

    MKMapPoint regionOrigin = MKMapPointForCoordinate(centerCoordinate); 
    MKMapRect regionRect = (MKMapRect){regionOrigin, radiusSquared}; //origin is the top-left corner 

    regionRect = MKMapRectOffset(regionRect, -radiusInMapPoints/2, -radiusInMapPoints/2); 

    // clamp the rect to be within the world 
    regionRect = MKMapRectIntersection(regionRect, MKMapRectWorld); 

    MKCoordinateRegion region = MKCoordinateRegionForMapRect(regionRect); 
    return region; 
} 


- (IBAction)setMap:(id)sender { 
    switch (((UISegmentedControl*) sender).selectedSegmentIndex) { 
     case 0: 
      _mapView.mapType = MKMapTypeStandard; 
      break; 
     case 1: 
      _mapView.mapType = MKMapTypeSatellite; 
      break; 

     case 2: 
      _mapView.mapType = MKMapTypeHybrid; 
      break; 
    } 
} 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:detailSegueName]) { 
     [[segue destinationViewController] setRun:self.run]; 
    } 
} 

回答

-1
saveRun變化

self.managedObjectContext[(AppDelegate*)[UIApplication sharedApplication].delegate managedObjectContext] ......

+0

乾杯夥計,這個工作對我來說:),得到一個數組越界異常,但現在生病揣摩原因再次發帖之前,謝謝。 – fredEtch

+0

很好聽,所以接受答案:-) – thorb65

1

這基本上是你的核心數據堆棧設置不正確時,調用該方法。 (可能self.managedObjectContext爲零)

雖然什麼thorb65 suggests可能會工作,我不會推薦它。你想用依賴注入來做什麼是一個更好的主意,但顯然,在這種情況下,由於某種原因,上下文還沒有被插入(或創建)。可能是由於國家恢復?

您的其他選擇是將核心數據堆棧設置在中央位置而不是應用程序委託,這樣,只要您嘗試使用它,就會始終設置它。我成功地使用了SLCoreDataStack,不過還有很多其他的,你自己創建一個類似的結構並不難。

+0

你錯了。 moc設置正確,但他沒有在應用程序委託中引用moc對象,所以view控制器中的self.managedObjectContext總是爲零。它不是一個問題,使用它的方式我寫... – thorb65

+0

這是一個非常積極的聲明,因爲我說你的方法將工作。我不同意的是:在應用程序委託中創建核心數據堆棧;並從應用程序的任何其他位置訪問應用程序委託。 –

+0

不同意或不...... appdelegate不是別的,而是一個單身人士。如果你知道你在做什麼,並關心線程等使用它沒有問題。我已經在一些非常簡單的應用程序中爲這樣的客戶使用它,並且從來沒有遇到過問題。對於更大的應用程序,我使用我自己的單例作爲moc和實體,從來沒有任何上下文或保存或線程問題。 – thorb65

1

您的CardioViewController有一個屬性self.managedObjectContext,但代碼中沒有任何內容顯示賦值給它的值。結果,它是零。你會得到這個例外,因爲你的代碼在沒有任何價值時試圖使用self.managedObjectContext

您的應用程序委託創建託管對象上下文,但這本身還不夠。它不會自動傳播到視圖控制器。在您的應用程序委託中,您需要將視圖控制器的NSManagedObjectContext賦予與在應用程序委託中創建的值相同的值。您的代碼不顯示在CardioViewController任何引用,但它可能

self.cardioViewController.managedObjectContext = self.managedObjectContext;