15

我正在尝试设置我的应用程序,以便在首次启动时,将位于主包中“Populator”文件夹中的一系列文件复制到文档目录中。

我目前的实现如下:

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

  NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Populator"];
  NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:@"Files"];
  NSLog(@"Source Path: %@\n Documents Path: %@ \n Folder Path: %@", sourcePath, documentsDirectory, folderPath);

  NSError *error;

  [[NSFileManager defaultManager] copyItemAtPath:sourcePath 
                                        toPath:folderPath
                                         error:&error];

  NSLog(@"Error description-%@ \n", [error localizedDescription]);
  NSLog(@"Error reason-%@", [error localizedFailureReason]);
  ....
  return YES;
}

但是,第一次使用以下控制台消息运行时会崩溃(但文件已被复制)。下次打开应用程序时,它不会崩溃。

    2010-07-13 15:14:26.418 AppName[5201:207] Source Path: /Users/jack/Library/Application Support/iPhone Simulator/3.2/Applications/1076C1FA-60B0-4AC7-8CD4-74F81472DAE6/AppName.app/Populator
 Documents Path: /Users/jack/Library/Application Support/iPhone Simulator/3.2/Applications/1076C1FA-60B0-4AC7-8CD4-74F81472DAE6/Documents 
 Folder Path: /Users/jack/Library/Application Support/iPhone Simulator/3.2/Applications/1076C1FA-60B0-4AC7-8CD4-74F81472DAE6/Documents/Files
2010-07-13 15:14:26.466 AppName[5201:207] *** +[AppNameAppDelegate localizedDescription]: unrecognized selector sent to class 0xa79c
2010-07-13 15:14:26.475 AppName[5201:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[AppNameAppDelegate localizedDescription]: unrecognized selector sent to class 0xa79c'
2010-07-13 15:14:26.495 AppName[5201:207] Stack: (
    40911435,
    2569270537,
    41183227,
    40645910,
    40642578,
    9142,
    2815466,
    2819475,
    2844680,
    2826401,
    2858055,
    49271164,
    40452156,
    40448072,
    2817668,
    2850273,
    8776,
    8630
)

有人对出了什么问题有任何建议吗?我已经设置了一些代码来实现“仅在首次启动时”功能,但为了清楚起见,这里没有包含它。

谢谢

4

6 回答 6

15
于 2010-07-13T14:30:05.290 回答
5

我刚刚阅读了我的代码并发现了问题。正如肖恩·爱德华兹(Sean Edwards)在上面指出的那样,如果成功就没有错误-因此会崩溃。

这是我给感兴趣的人的新代码:

if([[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:folderPath error:&error]){
    NSLog(@"File successfully copied");
} else {
    NSLog(@"Error description-%@ \n", [error localizedDescription]);
    NSLog(@"Error reason-%@", [error localizedFailureReason]);
}
于 2010-07-13T14:29:53.683 回答
4

我对 iPhone 编程或目标 C 了解不多,但出于好奇,如果复制操作确实成功,那么在这种情况下会出现什么错误?如果没有错误,可能是日志行崩溃了吗?

[编辑] 另外,您可以像这样复制子目录的全部内容吗?(同样,我不熟悉 iOS API,只是根据我对其他语言/API 的了解来识别可能的错误来源)

于 2010-07-13T14:28:45.057 回答
4

you should check whether the file already exists! Then copy.

+ (BOOL) getFileExistence: (NSString *) filename
{
    BOOL IsFileExists = NO;

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [documentPaths objectAtIndex:0];
    NSString *favsFilePath = [documentsDir stringByAppendingPathComponent:filename];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    // Check if the database has already been created in the users filesystem
    if ([fileManager fileExistsAtPath:favsFilePath])
    {
        IsFileExists = YES;
    }
    return IsFileExists;
}

+ (NSString *)dataFilePath:(NSString *)filename {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDirectory = [paths objectAtIndex:0];
    return [docDirectory stringByAppendingPathComponent:filename];
}

- (void)copyFileToLocal:(NSString *)filename
{

    if (![AppDelegate getFileExistence:filename])
    {
        NSError *error;
        NSString *file = [[NSBundle mainBundle] pathForResource:filename ofType:nil];

        if (file)
        {
            if([[NSFileManager defaultManager] copyItemAtPath:file toPath:[AppDelegate dataFilePath:filename] error:&error]){
                NSLog(@"File successfully copied");
            } else {

                [[[UIAlertView alloc]initWithTitle:NSLocalizedString(@"error", nil) message: NSLocalizedString(@"failedcopydb", nil)  delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil)  otherButtonTitles:nil] show];
                NSLog(@"Error description-%@ \n", [error localizedDescription]);
                NSLog(@"Error reason-%@", [error localizedFailureReason]);
            }
            file = nil;
        }
    }
}

NSLocalizedString are localize strings of the application.

于 2013-04-02T06:26:05.090 回答
2

You log an error before you know that there is an error

put the code in an if-block

if(error)
{
 NSLog(@"Error description-%@ \n", [error localizedDescription]);
 NSLog(@"Error reason-%@", [error localizedFailureReason]);
}

To describe your problem in more detail: the pointer of error points ANYWHERE and that object does not recognize that message. Therefore you get an exception

于 2010-07-13T14:32:02.277 回答
1

As a general programming practice, it's always best to initialize your variables with a default value:

NSError *error = nil;

In Objective-C, it is valid to send a message to nil. So, in your case, error variable would not cause a crash if it was initialized to nil.

For more info on the subject check Sending Messages to nil section at https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html

于 2012-06-07T12:08:33.163 回答