3

Я пытаюсь сделать приложение iPhone с использованием Core Data. Я должен использовать NSManagedObjectContext для доступа к данным, и для этого я использую UIManagedDocument. Но если я попытаюсь создать документ с UIManagedDocument, то openWithCompletionHandler документа не будет успешным. Это почему мой NSManagedObjectContext всегда nil и Xcode говорит, что не может создать документ на и т.д. Вот классы:Не удалось создать UIManagedDocument

AddUserViewController.h

#import <UIKit/UIKit.h> 

@interface AddUserViewController : UIViewController 

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 
@property (nonatomic,strong) UIManagedDocument *document; 

@end 

AddUserViewController.m

#import "AddUserViewController.h" 
#import "User.h" 
#import "User+Create.h" 

@interface AddUserViewController() 
@property (weak, nonatomic) IBOutlet UITextField *nameField; 
@property (weak, nonatomic) IBOutlet UITextField *ageField; 
@property (weak, nonatomic) IBOutlet UITextField *sexField; 
@property (weak, nonatomic) IBOutlet UITextField *weightField; 
@property (weak, nonatomic) IBOutlet UITextField *activityField; 


@end 

@implementation AddUserViewController 

-(void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ 
     _managedObjectContext = managedObjectContext; 
} 



-(void)createOrWriteDocument{ 
    NSURL *url = [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask]firstObject]; 
    url = [url URLByAppendingPathComponent:@"Activities"]; // edited mistakenly deleted 
    self.document = [[UIManagedDocument alloc] initWithFileURL:url]; 

    if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) { 
     [self.document openWithCompletionHandler:^(BOOL success) { 
      if (success) [self documentIsReady]; 
      if (!success){ 
       NSLog(@"could not open document at %@",url); 
      } 

     }]; 


    } else { 
     [self.document saveToURL:url 
      forSaveOperation:UIDocumentSaveForCreating 
      completionHandler:^(BOOL success) { 
       if (success) { 
        [self documentIsReady]; 
       } 
       if (!success){ 
        NSLog(@"could not create document at %@",url); 
       } 
      }]; 
    } 

} 


- (void)documentIsReady 
{ 
    if (self.document.documentState == UIDocumentStateNormal) { 
     self.managedObjectContext = self.document.managedObjectContext; 
    } } 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    if (!self.managedObjectContext) { 
     [self createOrWriteDocument]; 
    } 

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] 
            initWithTarget:self 
            action:@selector(dismissKeyboard)]; 

    [self.view addGestureRecognizer:tap]; 
} 

-(void)dismissKeyboard{ 
    [self.nameField resignFirstResponder]; 
    [self.ageField resignFirstResponder]; 
    [self.sexField resignFirstResponder]; 
    [self.weightField resignFirstResponder]; 
    [self.activityField resignFirstResponder]; 
} 

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ 

    if ([segue.identifier isEqualToString:@"setUser:"]) { 

     //User *user = [[User alloc]init]; 
     User *user = [User createUserWithname:self.nameField.text 
             withAge:[NSNumber numberWithDouble:[self.ageField.text doubleValue]] 
             withSex:self.sexField.text 
            withWeight:[NSNumber numberWithDouble:[self.weightField.text doubleValue]] 
           withActivity:self.activityField.text 
         inManagedObjectContext:self.managedObjectContext]; 

     if ([segue.destinationViewController respondsToSelector:@selector(setUser:)]) { 
      [segue.destinationViewController performSelector:@selector(setUser:) withObject:user]; 

     } 
    } 

} 

@end 

EDIT

Я решил проблему. Проблема находится на NSURL *url = [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask]firstObject]; линия. Вместо NSDocumentationDirectory я использовал NSDocumentDirectory и решил проблему.

+0

Я использую UIManagedDocument для приложения я работаю, и единственное основное различие я вижу в том, что я добавляю имя моего документа к концу URL-адрес. Я также захватываю lastObject из fileManager. Ex.NSURL * managedDocumentURLPath = [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject]; managedDocumentURLPath = [managedDocumentURLPath URLByAppendingPathComponent: @ "AppNameDocument"]; – Jonathan

+0

Когда я удалил строки комментариев, чтобы написать код здесь, я удалил эту строку. Тот же код, но не во мне. – Anamort

ответ

0

Вы можете попробовать этот код для создания управляемых объектов.

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

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

Взгляните на приведенный ниже пример. Это работает для меня, жаль, что у меня нет времени, чтобы взглянуть на различия, я использую параметры iCloud, поэтому удалите их, но попробуйте установить другие persistentStoreOptions. А также детали сообщения об ошибке вы получаете?

// This gets called when the user has done one of the following: 
// 1. Created a new file and entered a new file name. We have then created the fileURL 
//  using the /Documents directory, the filename and appending '_UUID_'+uuid to ensure that 
//  avoid duplicate file names in case the user used the same file name on another device. 
// 2. Selected an existing file from the file browser 
// 
- (void)createNewFile:(NSURL*)fileURL { 

    //FLOG(@"createNewFile called with url %@", fileURL); 

    _creatingNewFile = YES; // Ignore any file metadata scan events coming in while we do this because some iCloud 
          // files get created by Core Data before the local files are created and our scanning 
          // picks up new iCloud files and attempts to create local copies and we don't want this 
          // if this devices is busy creating the new iCloud file 

    _document = [[OSManagedDocument alloc] initWithFileURL:fileURL]; 

    // Set oberving on this file to monitor the state (we don't use it for anything other than debugging) 
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 
    [center addObserver:self 
       selector:@selector(documentStateChanged:) 
        name:UIDocumentStateChangedNotification 
       object:_document]; 

    _openedVersion = [NSFileVersion currentVersionOfItemAtURL:fileURL]; 
    _openedVersionDate = _openedVersion.modificationDate; 
    _openedVersionDevice = _openedVersion.localizedNameOfSavingComputer; 
    //FLOG(@" file version date: %@", _openedVersionDate); 
    //FLOG(@" file version device: %@", _openedVersionDevice); 

    NSString *fileName = [[fileURL URLByDeletingPathExtension] lastPathComponent]; 

    [_document setPersistentStoreOptions:@{NSPersistentStoreUbiquitousContentNameKey:fileName, 
              NSMigratePersistentStoresAutomaticallyOption:@YES, 
              NSInferMappingModelAutomaticallyOption:@YES, 
              NSSQLitePragmasOption:@{ @"journal_mode" : @"DELETE" }}]; 

    _managedObjectContext = _document.managedObjectContext; 

    if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { 
     //FLOG(@" file exists so open it: %@",fileURL); 
     [_document openWithCompletionHandler:^(BOOL success){ 
      if (!success) { 
       // Handle the error. 
       LOG(@" error creating file"); 
      } else { 
       //LOG(@" file opened"); 
       [self fileOpened]; // Now initialise the UI and let the user continue... 
      } 
     }]; 

    } 
    else { 
     // File does not exist so that means the user has created a new one and we need to 
     // load some initialisation data into the Core Data store (codes tables, etc.) 
     // 
     // At this stage we have a database in memory so we can just use the _document.managedObjectContext 
     // to add objects prior to attempting to write to disk. 

     //LOG(@" file DOES NOT exist so add initial data"); 
     [self addInitialData]; 

     // Just checking if anything has been written to disk, nothing should not exist on disk yet. 
     // Debugging use only 
     if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) 
      LOG(@" file exists but keep going anyway :-("); 
     else 
      LOG(@" file still does not exist :-)"); 


     // OK now save a copy to disk using UIManagedDocument 
     // NOTE: the iCloud files are written before the UIManagedDocument.fileURL, presumably because Core Data does this setup 
     // in response to the [moc save:]. Make sure we don't pick this up in our iCloud metaData scan and attempt to create 
     // it as if it were a new iCloud file created by some other device. 
     // 
     [_document saveToURL:_document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){ 
      if (!success) { 
       // Handle the error. 
       LOG(@" error saving file :-("); 
      } 

      // We close the file and wait for it to appear in the file browser and then 
      // let the user select it from the browser to open it and start using it. 
      // Skip this if you want to open it directly and [self fileopened] but 
      // bear in mind the fileListController will not be correctly set up when we return to it. 

      [_document closeWithCompletionHandler:^(BOOL success){ 
       if (!success) { 
        // Handle the error. 
        LOG(@" error closing file after creation :-("); 
        FLOG(@" file URL is %@", [fileURL path]); 
       } else { 
        FLOG(@" file closed %@", fileName); 

        _creatingNewFile = NO; // OK we are done, so let metaData scanning go ahead as normal 

        // Tell our UITableView file list that we are done and trigger scanning of local and iCloud files 
        // The fileListController will the add the new file itself and the user will then pick the 
        // file from this list in order to open it. 

        // To open the file automatically use the callback in the fileListController 
        // to select and then open the file so it looks seamless to the user. 
        [self.fileListController fileHasBeenCreated:fileURL]; 


        // Stop observing now 
        [center removeObserver:self 
             name:UIDocumentStateChangedNotification 
            object:_document]; 

       } 
      }]; 
     }]; 
    } 
} 

О, а также создать подкласс UIManagedDocument, так что вы можете получить ошибки, если вы уже не один. Все, что вам нужно, это следующее в подклассе.

@implementation OSManagedDocument 


- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError 
{ 
    LOG(@"Auto-Saving Document"); 
    return [super contentsForType:typeName error:outError]; 
} 

- (void)handleError:(NSError *)error userInteractionPermitted:(BOOL)userInteractionPermitted 
{ 
    FLOG(@" error: %@", error.localizedDescription); 
    NSArray* errors = [[error userInfo] objectForKey:NSDetailedErrorsKey]; 
    if(errors != nil && errors.count > 0) { 
     for (NSError *error in errors) { 
      FLOG(@" Error: %@", error.userInfo); 
     } 
    } else { 
     FLOG(@" error.userInfo = %@", error.userInfo); 
    } 
} 
@end 

Это способ получить каталог/Documents на устройстве. Имя файла добавляется к этому пути.

- (NSURL*)documentsDirectoryURL 
{ 
    _dataDirectoryURL = [NSURL fileURLWithPath:NSHomeDirectory() isDirectory:YES]; 
    return [_dataDirectoryURL URLByAppendingPathComponent:@"Documents"]; 
} 

Вот ссылка на более подробную информацию http://ossh.com.au/design-and-technology/software-development/uimanageddocument-icloud-integration/