簡體   English   中英

iPhone(iOS):將文件從主包復制到文檔文件夾會導致崩潰

[英]iPhone (iOS): copying files from main bundle to documents folder causes crash

我正在嘗試設置我的應用程序,以便在首次啟動時,位於主包中“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
)

有沒有人對什么出錯有任何建議? 我已經設置了一些代碼來實現“僅在首次啟動時”功能,但為了清楚起見,此處未將其包括在內。

謝謝

   NSError *error;

您正在聲明一個局部變量而不初始化它。 因此,它將充滿垃圾。

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

如果此行沒有發生error ,則仍會保留error的垃圾狀態。

  NSLog(@"Error description-%@ \n", [error localizedDescription]);

現在,您將消息發送到一些隨機的,未初始化的位置。 這是崩潰的根源。


為避免這種情況,請將error初始化為nil

NSError* error = nil;
//             ^^^^^

或者僅在-copyItemAtPath:…返回NO(其中正確填充error )時打印錯誤。

if (![[NSFileManager defaultManager] copyItemAtPath:sourcePath ...]) {
  NSLog(...); 
}

我只是閱讀了我的代碼並發現了問題。 正如肖恩·愛德華茲指出的那樣,如果成功就沒有錯誤 - 因此崩潰。

這是我感興趣的新代碼:

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]);
}

你應該檢查文件是否已經存在! 然后復制。

+ (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是應用程序的本地化字符串。

我不太了解iPhone編程或目標C,但出於好奇,如果復制操作實際成功,那么錯誤是什么? 如果沒有錯誤,它可能是崩潰的日志行嗎?

[編輯]另外,你是否可以復制像這樣的子目錄的全部內容? (同樣,我不熟悉iOS API,根據我所知道的其他語言/ API識別可能的錯誤來源)

您在知道錯誤之前記錄錯誤

將代碼放在if塊中

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

更詳細地描述您的問題:錯誤指針指向ANYWHERE,該對象無法識別該消息。 因此你得到一個例外

作為一般編程實踐,最好使用默認值初始化變量:

NSError *error = nil;

在Objective-C中,向nil發送消息是有效的。 因此,在您的情況下,如果錯誤變量初始化為nil則不會導致崩潰。

有關該主題的更多信息,請參閱https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html上的“將Sending Messages to nil部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM