programing

첫 번째 앱 업데이트, 사용자 데이터 손실 (문서 디렉토리에 저장 됨)

copyandpastes 2021. 1. 15. 20:18
반응형

첫 번째 앱 업데이트, 사용자 데이터 손실 (문서 디렉토리에 저장 됨)


내 첫 번째 앱 업데이트가 어제 밤에 게시되었으며 업데이트로 인해 사용자가 만든 데이터 (일부)가 사라 졌다는 불만이 있습니다. 문제를 재현 할 수 있었지만 이유를 알 수 없습니다.

Documents 디렉토리에 모든 사용자 파일의 "제목"과 파일 이름 (전체 경로)을 알려주는 하나의 키 파일을 저장했습니다. 그런 다음 모든 사용자의 파일도 Documents 디렉토리에 있습니다.

업데이트가 발생하면 키 파일은 여전히 ​​존재하지만 (적어도 앱의 첫 번째 화면에 데이터가 표시되기 때문이라고 생각합니다. 앱은 업데이트 후 완전히 종료되고 다시 실행됩니다. 그렇죠?), 사용자가 시도하면 실제 파일을 탐색하기 위해 데이터가 없으며 사용자가 입력 한 새 데이터는 저장되지 않습니다.

실수로 잘못된 파일 이름 (부적절한 문자 포함)을 사용했을 때 디버깅에서와 똑같이 작동합니다. 저장되지 않았습니다. 그러나 업데이트를 통해 이러한 파일은 이전 버전에서는 제대로 저장되었지만 새 버전에서는 실패합니다.

이것은 내 첫 번째 앱이자 첫 번째 업데이트이며 여기에서 상당히 헤매고 있습니다. 지금은 앱 판매를 중단했으며 (단순히 이전 버전으로 되돌릴 수 없다는 것을 몰랐습니다! yikes!) 문제를 찾는 방법과 작성 방법에 대한 아이디어를 깊이 감사하겠습니다. 데이터를 잃지 않는 좋은 업데이트. (지금까지 내가 찾은 것은 "문서 디렉토리에 데이터 저장"뿐입니다.이 작업은 이미 수행하고 있습니다.)

원래 앱이 자체 프로젝트에 저장되어 있고 다시 돌아가서 작업 할 수 있습니다. 업데이트 작업을 시작할 때 전체 디렉토리를 복사했는데 그게 문제가 될 수 있는지 궁금합니다. 모든 XCode 파일을 보유하고있는 디렉토리의 이름을 변경하고 Project> Rename 기능을 사용했습니다. 그게 어떻게 든 이런 영향을 미칠 수 있을까요?

중요한 경우 앱 (원본 및 업데이트 모두)이 4.2 이상에서 실행되고 있습니다.

해결:

나는이 문제를 알아 냈다고 믿는다. 질문의 시작 부분에서 말했듯이 키 파일에 사용자 파일의 전체 경로를 저장했습니다. 분명히, 전체 경로가 업데이트 후 동일하다고 보장되지는 않습니다 (어딘가에 문서화되어 있다고 확신하지만 실행하지 않았습니다).

따라서 사용자 파일은 업데이트의 새 Documents 디렉토리로 전송되었지만, 샌드 박스가 아닌 이전 절대 경로에서 파일을 찾고있었습니다.

앱의 didFinishLaunching에 루프를 넣어 파일 경로의 문제가되는 파일을 꺼내고 (THAT, 저는 항상 로컬에서 찾았고 여전히 작동 중이었습니다) fileNAMES로 잘라내어 수정했습니다. 문서 경로는 파일 작업이 수행 될 때마다 프로그래밍 방식으로 찾아서 추가해야합니다.

원래 버전을 다시 설치해도 사용자 문제가 해결되지 않았을 것이기 때문에 스토어에서 이전 바이너리로 되돌릴 수있는 방법이 없다는 것이 실제로 저에게 좋았지 만 적어도 그럴 것이라고 믿었을 것입니다. 처음에는. 업데이트를 허용하지 않는 방법이 있었으면하지만 새 구매는 허용했습니다 (문제가 새 구매에 영향을 미치지 않았기 때문에). 그러나 그것을 보증하기에 충분한 일반적인 상황은 아닐 것입니다.


인터넷 통행인을 위해 이것에 대해 더 많은 것을 밝히기 위해. 예, OP는 마지막에 자신의 질문에 대답했습니다. 문서 디렉토리에 파일에 대한 절대 URL을 저장해서는 안되며 그렇게하면 데이터가 손실 될 수 있습니다 . 이는 앱을 업데이트 할 때 .plist 파일에서 버전 번호를 변경하여 iOS가 다른 16 진수 이름으로 해당 앱에 대한 새 디렉터리를 생성하기 때문입니다. 이제 절대 URL이 잘못된 위치를 참조하고 있으며 적절한 파일을 반환하지 않습니다.

다음으로 이동하여 장치에 배포하기 전에 자신의 컴퓨터에서 확인할 수 있습니다.

~ / Library / Application Support / iPhone Simulator / * ios_version * / Applications /

다음과 같은 이름의 폴더가 표시됩니다.

6AA4B05C-8A38-4469-B7BE-5EA7E9712510 CB43C5F3-D720-49C3-87D4-EBE93FFD428B

이 폴더 안에는 iOS 앱용 표준 파일 시스템 레이아웃이 있습니다.

문서 라이브러리 tmp YourApp.app

전체 URL을 참조하면 다음과 같은 내용이 표시됩니다.

~ / Library / Application Support / iPhone Simulator / * ios_version * / Applications / 6AA4B05C-8A38-4469-B7BE-5EA7E9712510 / Documents / MyVeryImportantUserData.txt

그러나 앱을 업데이트 할 때 앱이 시도 할 새 URL은 다음과 같습니다.

~ / Library / Application Support / iPhone Simulator / * ios_version * / Applications / CB43C5F3-D720-49C3-87D4-EBE93FFD428B / Documents / MyVeryImportantUserData.txt

비어 있습니다.

대신 문서 디렉토리 파일 경로 접두사를 얻은 후에 만 ​​파일 경로를 저장하여 항상 동적 참조를 만들어야합니다.

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

원본 포스터에 절대 URL을 가져와 문자열의 문서 부분을 통해 모든 것을 잘라내도록 코드를 수정 한 새로운 업데이트를 발행하여 사용자 손실 데이터를 저장할 수 있습니다 . 그런 다음 파일 경로에 적절한 문서 디렉토리 URL을 접두사로 붙이면 앱이 데이터를 찾았을 것입니다.


질문 포스터와 첫 번째 답변은 정확히 무슨 일이 일어나고 있는지 명확히하는 데 도움이되었습니다.

그래서 그들의 관찰을 바탕으로 문서 폴더로 이어지는 경로 내의 폴더 이름이 바뀌 었다는 것을 알게되었습니다. 이로 인해 파일의 fileNames 만 저장하고 저장된 파일 이름의 현재 fullPath 문자열을 가져오고 앱 업데이트 후 현재 문서 폴더에 저장 되는 유틸리티 클래스를 만드는 솔루션이 제공 됩니다.

#import "StringUtils.h"

@implementation StringUtils

+ (NSString *)getFullDocumentUrl:(NSString *)fileName
{
    return [NSString stringWithFormat:@"%@/%@",[self applicationDocumentsDirectory],fileName];
}

+ (NSString *)applicationDocumentsDirectory
{
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

@end

나는 같은 문제에 부딪쳤다. 다음은 문서 디렉토리의 파일을 반복하고 파일 이름은 그대로두고 파일 경로 정보를 대체하여 파일 이름을 수정하는 몇 가지 예제 코드입니다. 파일 이름을 변경하기 위해 마지막 줄을 실행하기 전에 NSLog를 사용하여 이것이 updatedName에서 정확히 원하는 것인지 확인하는 것이 좋습니다.

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *filenames = [fm contentsOfDirectoryAtPath:documentsPath error:nil];

    //Match on the filepath leading up to docs directory
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^/\\S*Documents/"
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:nil];
    for (NSString *fileName in filenames)
    {
        NSRange fullLength = NSMakeRange(0, [fileName length]);
        //swap out the prepended directory structure with an empty string
        NSString *updatedFileName = [regex stringByReplacingMatchesInString:fileName
                                                                    options:0
                                                                      range:fullLength
                                                               withTemplate:@""];
        NSString *currentName = [NSString stringWithFormat:@"%@/%@",documentsPath,fileName];
        NSString *updatedName = [NSString stringWithFormat:@"%@/%@",documentsPath,updatedFileName];
        [fm moveItemAtPath:currentName toPath:updatedName error:nil];
    }

To get the current Document Directory path

NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String

You can user this function to find new dicrectorty of documents

ex: this is first time you build app and save photo to this url

"file:///var/mobile/Containers/Data/Application/D79E1373-883C-412B-B84E-5C1E47BD0BEC/Documents/Temp/Photo_65650205603482916.jpg"

after that you rebuild app the doc direct is chaged to

file:///var/mobile/Containers/Data/Application/E387590D-B279-4C38-A601-65C6F7BC917D/Documents/

so you can't not upload when use old url

When upload you can do this:

// you have photoURl 

func getURLtoUpload(photoUrl:URL) {
    let urlStr = photoUrl.lastPathComponent

    let fileURL = self.getDocumentsDirectory().appendingPathComponent("Temp").appendingPathComponent("\(urlStr)")
    // your url to upload here 
    let url = URL(string:fileURL)
}


func getDocumentsDirectory() -> URL {

    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}

If you want to save the location of a file persistently, use the bookmark capabilities of NSURL. A bookmark is an opaque data structure, enclosed in an NSData object, that describes the location of a file. Whereas path- and file reference URLs are potentially fragile between launches of your app, a bookmark can usually be used to re-create a URL to a file even in cases where the file was moved or renamed.

https://stackoverflow.com/a/53274341/945906

ReferenceURL : https://stackoverflow.com/questions/5607655/first-app-update-user-data-lost-was-stored-in-documents-directory

반응형