2012-12-19 58 views
4

我一直在努力想弄清楚如何建立我的SQL數據庫的核心數據&之間的連接。該數據庫不是預先填充的,但它會在啓動時用於許多不同的用戶。核心數據到SQL不起作用

我已經通過斯坦福三次提供的iCloud課程核心數據&無果。我也仔細研究了iOS中的SQLite/SQL關係數據庫無濟於事。我唯一的選擇就是來到這裏,發佈我所能得到的所有代碼,並祈禱有人會爲我提供一個答案。所以這裏有雲......

AppDelegate.m

- (void)saveContext 
{ 
    NSError *error = nil; 
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 
    if (managedObjectContext != nil) { 
     if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 

      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
    } 
} 

#pragma mark - Core Data stack 

- (NSManagedObjectContext *)managedObjectContext 
{ 
    if (_managedObjectContext != nil) { 
     return _managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     _managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 
    return _managedObjectContext; 
} 

- (NSManagedObjectModel *)managedObjectModel 
{ 
    if (_managedObjectModel != nil) { 
     return _managedObjectModel; 
    } 
    NSURL *modelURL = [self applicationDocumentsDirectory]; 
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    return _managedObjectModel; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    if (_persistentStoreCoordinator != nil) { 
     return _persistentStoreCoordinator; 
    } 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"shindy.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 

- (NSURL *)applicationDocumentsDirectory 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"shindy.sqlite"]; 

    return [NSURL fileURLWithPath:path]; 
} 

HomeViewController.m

- (void)setupFetchedResultsController 
{ 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"]; 
    request.sortDescriptors = [NSArray arrayWithObjects: 
           [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:@"location" ascending:YES], 
                            nil]; 

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request 
                     managedObjectContext:self.shindyDatabase.managedObjectContext 
                      sectionNameKeyPath:nil 
                        cacheName:nil]; 

} 

- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document 
{ 
    dispatch_queue_t fetchQ = dispatch_queue_create("Shindy Fetcher", nil); 
    dispatch_async(fetchQ, ^{ 
     NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; 
     NSLog(@"shindys = %@", shindys); 
     [document.managedObjectContext performBlock:^{ 
      for (NSDictionary *shindyInfo in shindys) { 
       [Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext]; 
       NSLog(@"fire"); 
      } 
     }]; 
    }); 
} 

- (void)useDocument 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"shindy.sqlite"]; 

    if (![[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]) { 
     [self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { 
      [self setupFetchedResultsController]; 
      [self fetchShindyDataIntoDocument:self.shindyDatabase]; 
     }]; 
    } else if (self.shindyDatabase.documentState == UIDocumentStateClosed) { 
      [self.shindyDatabase openWithCompletionHandler:^(BOOL success) { 
     [self setupFetchedResultsController]; 
     }]; 
    } else if (self.shindyDatabase.documentState == UIDocumentStateNormal) { 
     [self setupFetchedResultsController]; 
    } 
} 

- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase 
{ 
    [self useDocument]; 
} 

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

    [self fetchShindyDataIntoDocument:self.shindyDatabase]; 

    if (!self.shindyDatabase) { 
     [self setShindyDatabase:self.shindyDatabase]; 
    } 
} 

希迪+ ShindyDB.m

+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo 
      inManagedObjectContext:(NSManagedObjectContext *)context 
{ 
    Shindy *shindy = nil; 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"]; 

    NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES]; 
    NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES]; 
    NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:@"location" ascending:YES]; 
    NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; 
    NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES]; 
    NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES]; 
    // title 
    request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil]; 

    NSError *error = nil; 
    NSArray *matches = [context executeFetchRequest:request error:&error]; 

    if (!matches || ([matches count] > 1)) { 
     // handle error 
    } else if ([matches count] == 0) { 
     shindy = [NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:context]; 

     shindy.dateAndTime = [shindyInfo objectForKey:@"dateAndTime"]; 
     shindy.details = [shindyInfo objectForKey:@"details"]; 
     shindy.location = [shindyInfo objectForKey:@"location"]; 
     shindy.name = [shindyInfo objectForKey:@"name"]; 
     shindy.photo = [shindyInfo objectForKey:@"photo"]; 
     shindy.timePosted = [shindyInfo objectForKey:@"timePosted"]; 
     // title 
     // Guestlist? The rest? 
     // Use below for reference 
     shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:@"whoseShindy"] inManagedObjectContext:context]; 
    } else { 
     shindy = [matches lastObject]; 
    } 

    shindy = [NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:context]; 
    shindy.dateAndTime = [shindyInfo objectForKey:@"dateAndTime"]; 
    shindy.details = [shindyInfo objectForKey:@"details"]; 
    shindy.location = [shindyInfo objectForKey:@"location"]; 
    shindy.name = [shindyInfo objectForKey:@"name"]; 
    shindy.photo = [shindyInfo objectForKey:@"photo"]; 
    shindy.timePosted = [shindyInfo objectForKey:@"timePosted"]; 

    return shindy; 
} 

AddShindyViewController.m

- (void)saveShindyToDatabase 
{ 
    NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; 
    [self.shindyDatabase.managedObjectContext performBlock:^{ 
     for (NSDictionary *shindyInfo in shindys) { 
      [Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:self.shindyDatabase.managedObjectContext]; 

      NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
      // url = [url URLByAppendingPathComponent:@"Default Shindy Database"]; 
      self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url]; 

      [self.shindyDatabase setValue:self.detailView.text forKey:@"details"]; 

      if (FBSession.activeSession.isOpen) { 
       [[FBRequest requestForMe] startWithCompletionHandler: 
        ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) { 
         if (!error) { 
          self.name = user.name; 
          self.photo.profileID = user.id; 
          self.username = user.username; 
         } 
        }]; 
      } 
      [self.shindyDatabase setValue:self.name forKey:@"name"]; 
      [self.shindyDatabase setValue:self.photo forKey:@"photo"]; 
      [self.shindyDatabase setValue:self.username forKey:@"username"]; 
      // [Guest guestWithName:self.name username:self.username photo:self.photo inManagedObjectContext:self.shindyDatabase.managedObjectContext]; 
      [self.shindyDatabase setValue:self.locationManager.location forKey:@"location"]; 
      [self.shindyDatabase setValue:self.dateAndTimePicker.date forKey:@"dateAndTime"]; 
     } 
    }]; 
} 

我知道我所要求的是多麼地獄,但我已經耗盡了我掌握的每一項資源。如果任何人甚至可以指向正確的方向,我會永遠感激!

+0

首先,如果你的問題是映射一個現有的數據庫,忘記它,你不能這樣做。否則,嘗試實現一些錯誤日誌記錄,例如,如果你寫了'//處理錯誤'嘗試添加[錯誤localizedDescription],也放一些斷點,看看是否調用方法,然後一步一步地看看它的中斷。 – Leonardo

回答

1

如果您計劃使用CoreData映射現有數據庫,您將會失敗。 實際上,你無法用CoreData映射任何數據庫。

核心數據infact是一個圖形對象管理,具有不同的存儲選項,而sqllite只是其中一種可能性。在啓動時,如果選擇sqllite作爲選項,則應用程序將創建一個具有特定表結構的數據庫。如果您嘗試連接到未由CoreData框架創建的數據庫,則會出現錯誤。

你可以做的是擺脫CoreData,並建立你的NSObject行爲像實體。但是,那麼你將不得不實現所有的邏輯來保存,更新,版本化,併發ecc ......並且這是一個很長的(並且很麻煩)的方式,尤其是在多用戶環境中。

否則,告訴我,我是否誤解了你的問題。也許,你可以發佈一個錯誤堆棧跟蹤。

+1

要根據https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdPersistentStores.html提供確切的報價:「重要提示:儘管Core Data支持SQLite作爲商店類型,商店格式(如其他本地Core Data存儲的格式)是私有的。您不能使用本機SQLite API創建SQLite數據庫,並直接將其與Core Data一起使用(也不應該使用本機SQLite API來操作現有的Core Data SQLite存儲) 。如果你有一個現有的SQLite數據庫,你需要將它導入到一個Core Data存儲中(請參閱「高效導入數據」)。「 – Tommy

+1

此外,我想知道爲什麼這個問題有這麼多的票!在這樣一個衆所周知的主題上。 – Leonardo

+0

我明白你已經說過了。我發佈了我的代碼,因爲據我所知,我已經正確編寫了所有代碼,但是,我沒有收到錯誤堆棧。事實上,我沒有通過數據庫/核心數據得到任何反饋。我非常仔細地查看了我發佈的代碼,但我不明白爲什麼它不起作用。我的問題是:爲什麼它不工作? – jakenberg