Objective-C чтение/запись в файл plist//после попытки 9999 различных решений

Как я уже сказал в теме, у меня возникают проблемы как с чтением, так и с записью в файл .plist. Я уже прочитал много возможных реализаций из других тем здесь и из книги, но все же я не могу заставить это работать, поэтому я хотел бы спросить ваше мнение. Прямо сейчас это происходит так:

У меня есть массив фильмов arrayMovies в диспетчере данных общего экземпляра. Я работаю все свое приложение на основе этого массива. Это всегда «доступно» из любой части приложения только этим:

[[iCultureDataManager sharedInstance]arrayMovies];

Поэтому, когда приложение завершает загрузку, я инициализирую arrayMovies из массива, который должен находиться в файле .plist, например так:

-(NSString* ) getFilePathForMovies{
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = [path objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingString:@"movies.plist"];
    return filePath;
}

- (NSArray *) getMovies{
    NSString *myPath = [self getFilePathForMovies];
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
    NSArray* movies;
    if(fileExists){
    movies = [[NSArray alloc ]initWithContentsOfFile:myPath];
    }
    return movies;
    }

и в инициализации я просто

_arrayMovies = [NSMutableArray arrayWithArray:[self getMovies]];

Одна вещь, которую я не понимаю, это почему BOOL fileExists всегда возвращает false, как будто он не находит файл .plist.

Чтобы сохранить массив для файла .plist, я делаю:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [self addToMovies];
    NSLog(@"DidEnterBackground: Adding to Movies...");
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self addToMovies];
    NSLog(@"applicationWillEnterForeground: Adding to Movies...");
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive.  If the application was previously in the background, optionally refresh the user interface.
    */
}


- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"applicationWillTerminate: Adding to Movies...");
    [self addToMovies];
}

- (void) addToMovies{
    NSString *myPath = [self getFilePathForMovies];
    [[[iCultureDataManager sharedInstance]arrayMovies] writeToFile:myPath atomically:YES];
}

-(NSString* ) getFilePathForMovies{
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = [path objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingString:@"movies.plist"];
    return filePath;
}

Я думаю, что это в значительной степени касается вопросов, но если я могу помочь вам с дополнительной информацией, не стесняйтесь сказать, потому что я действительно не понимаю, что происходит. Я не знаю, то ли я неправильно пишу в файл, то ли неправильно читаю, то ли еще что-то, что я делаю неправильно.

Большое спасибо за ваше время и помощь,

PS: теперь я нахожусь в точке, где fileExists всегда возвращает -1... :S


person ruitex23    schedule 30.12.2013    source источник
comment
Вы должны использовать stringByAppendingPathComponent вместо stringByAppendingString, потому что он правильно добавит косую черту между компонентами (возможно, у вас уже есть косая черта, но использование правильного метода гарантирует, что вы это сделаете). Кроме того, writeToFile:atomically: возвращает BOOL, указывающий на успех или нет, вы должны проверить это, чтобы увидеть, действительно ли вы пишете.   -  person rdelmar    schedule 30.12.2013


Ответы (2)


Вы подразумеваете, что инициализируете свой массив списком фильмов, которые находятся в файле plist. Это будет означать, что вы начинаете с файла plist. Чтобы получить доступ к файлу plist, доступному только для чтения, который существует в вашем комплекте, вы используете другой путь, подобный этому:

-(NSString *)getOriginalFilePathForMovies {
    NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"originalMovies" ofType:@"plist"];
    contentArray = [NSArray arrayWithContentsOfFile:plistPath];
}

Затем для доступа к доступному для записи plist вам нужен путь, который вы используете:

-(NSString* ) getFilePathForMovies{
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = [path objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingString:@"movies.plist"];
    return filePath;
}

Поэтому я бы рекомендовал сделать это для инициализации вашего массива:

- (NSArray *)getMovies {
    NSString *myPath = [self getFilePathForMovies];
    BOOL fileExists = [[NSFileManager defaultManager]fileExistsAtPath:myPath];
    NSArray* movies;
    if(fileExists){
        movies = [[NSArray alloc]initWithContentsOfFile:myPath];
    } else {
        movies = [[NSArray alloc]initiWithContentsOfFile:[self getOriginalFilePathForMovies]];
    return movies;
}
person HalR    schedule 30.12.2013
comment
В чем разница между двумя методами? Я не понимаю... Для чего нужны оригинальные фильмы? - person ruitex23; 30.12.2013
comment
getOriginalFilePathForMovies считывает доступный только для чтения файл из исходного пакета, поставляемого с приложением. getFilePathForMovies дает вам путь к файлу plist, в который вы можете читать и писать. Этот путь находится в каталоге ваших документов. - person HalR; 30.12.2013
comment
У вас есть файл plist, включенный в ваше приложение? - person HalR; 30.12.2013
comment
Да, в папке с моими ресурсами у меня есть фильмы.plist. Этого достаточно? - person ruitex23; 30.12.2013
comment
Вы изменили @originalMovies в моем getOriginalFilePathForMovies на фильмы? И этот файл открывается? - person HalR; 30.12.2013
comment
Да, я сделал, и файл пустой. Только говорит Рут. Нужно ли мне что-то добавить к нему? - person ruitex23; 30.12.2013
comment
Аааа.. Я неправильно вас понял. Я думал, у тебя есть фильмы, с которых ты хотел бы начать. Если вы не хотите начинать с некоторых фильмов в plist, я бы рекомендовал вам просто создать файл, если он еще не существует. - person HalR; 30.12.2013
comment
Попробуйте это: developer.apple.com/library /mac/documentation/Cocoa/Conceptual/ - person HalR; 30.12.2013

Вместо stringByAppendingString: вы должны использовать stringByAppendingPathComponent:. В противном случае ваш путь будет выглядеть как .../Documentsmovies.plist (я думаю).

РЕДАКТИРОВАТЬ: О, кто-то уже сказал в комментариях!

person fumoboy007    schedule 30.12.2013