【问题标题】:Could not create UIManagedDocument无法创建 UIManagedDocument
【发布时间】:2013-12-01 14:43:20
【问题描述】:

我正在尝试使用 Core Data 制作 iPhone 应用程序。我必须使用NSManagedObjectContext 来访问数据,为此我使用UIManagedDocument。但是如果我尝试使用UIManagedDocument 创建一个文档,则文档的openWithCompletionHandler 不会成功。这就是为什么我的NSManagedObjectContext 总是nil 而Xcode 说无法在等处创建文档。这里是类:

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

编辑

我解决了问题。问题在NSURL *url = [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask]firstObject]; 线。我使用 NSDocumentDirectory 而不是 NSDocumentationDirectory,它解决了问题。

【问题讨论】:

  • 我将 UIManagedDocument 用于我正在开发的应用程序,我看到的唯一主要区别是我将文档名称附加到 url 路径的末尾。我还从 fileManager 中获取了 lastObject。 Ex.NSURL * managedDocumentURLPath = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; managedDocumentURLPath = [managedDocumentURLPath URLByAppendingPathComponent:@"AppNameDocument"];
  • 当我删除了注释行-在这里写代码-时,我删除了这一行。相同的代码,但我失败了。

标签: ios objective-c nsmanagedobjectcontext uimanageddocument


【解决方案1】:

你可以试试这段代码来创建你的 managedobjectcontext。

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

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

【讨论】:

    【解决方案2】:

    看看下面的例子。这对我有用,抱歉没有时间仔细查看差异,我正在使用 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-15
      • 2012-05-25
      • 2012-05-06
      • 2016-05-22
      • 2012-08-22
      • 1970-01-01
      • 2013-03-04
      • 1970-01-01
      相关资源
      最近更新 更多