Сохранить содержимое NSMutableArray в файл

У меня есть приложение, в котором есть несколько ViewControllers. У каждого ViewController есть вопрос с 2-5 buttons возможными ответами. Название кнопки сохраняется в NSMutableArray с именем submission. Пользователь может вернуться к предыдущим вопросам, изменить свой ответ, и NSMutableArray будет соответствующим образом обновлен. Мне нужно сохранить этот массив в файл, чтобы новые результаты можно было сохранять в UITableView каждый раз, когда заполняется анкета. Я исследовал, и похоже, что .plist - хороший вариант, так как все мои объекты в массиве NSStrings.

Образец моего массива:

2013-12-17 14:06:34.210 Questionnaire[1724:70b] (
    1234,
    "Dec 17, 2013",
    Yes,
    Games,
    "Not Applicable",
    Yes
)

«1234» — это идентификатор пользователя, дата — это дата рождения, а остальные отправленные материалы — это ответы на каждый вопрос.

Мои ViewControllers выглядят так:

MainViewController
InfoViewController <-- Array allocated + initialised, inserting ID and DoB
Q1ViewController <-- question
..
Q4ViewController <--question
ENDViewController <-- offers user options for Home or Results
ResultsViewController <-- UITableView ordered by User ID
SavedResultsViewController <-- UITableView showing complete submission

NSMutableArray передается через каждый ViewController.

Мои вопросы: Какой метод сохранения в файл лучше всего подходит для моих нужд? (.plist, тип файла и т. д.). Было бы неплохо (но не обязательно) просмотреть результаты в Excel. Где должно происходить сохранение? Я думал, что когда последний объект вставляется в массив в Q4 ViewController, он будет сохранен в файл, когда ENDViewController выталкивается, это логично? Нужно ли мне создавать новый файл Objective-C для хранения данных? Я видел несколько руководств, объясняющих это, объявляя каждый объект в отдельном файле NSObject, хотя я не уверен, что это необходимо, поскольку мои объекты уже хранятся в массиве.

Как вы, наверное, догадались, я новичок в программировании на Objective-C и iOS, поэтому любая предложенная помощь приветствуется. Я не уверен, как еще описать мою проблему, поэтому извиняюсь, если вопрос все еще неясен.

Редактировать: я узнал немного больше о Objective-C с момента создания этого поста и решил сохранить свои данные в файле .csv. Этот файл предназначен исключительно для отправки по электронной почте, он не отображается на UITableView (в настоящее время я реализую для этого Core Data). Это решение может помочь кому-то в будущем, так что вот оно:

// Set column titles for .csv
NSArray *columnTitleArray = @[@"User ID", @"DoB", @"Question 1", @"Question 2", @"Question 3", @"Question 4"];

NSString *columnTitle = [columnTitleArray componentsJoinedByString:@","];
NSString *columnTitleToWrite = [columnTitle stringByAppendingString:@"\n"];

// Separate submissions from array into cells
NSString *questionResults = [self.submission componentsJoinedByString:@","];
NSString *questionResultsToWrite = [questionResults stringByAppendingString:@"\n"];

// Find documents directory
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// Set file name and type
NSString *survey = [docPath stringByAppendingPathComponent:@"result.csv"];
// Create new file if none exists
if (![[NSFileManager defaultManager] fileExistsAtPath:survey]){
    [[NSFileManager defaultManager] createFileAtPath:survey contents:nil attributes:nil];

    // Set column titles for new file
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:survey];
    [fileHandle writeData:[columnTitleToWrite dataUsingEncoding:NSUTF8StringEncoding]];
}

NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:survey];
[fileHandle seekToEndOfFile];
[fileHandle writeData:[questionResultsToWrite dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile]; 

person rosshump    schedule 17.12.2013    source источник
comment
Чтобы упростить задачу, вы можете начать с сохранения в plist. Для этого просмотрите это руководство .   -  person Jeremy    schedule 17.12.2013
comment
Я пытался изучить это с помощью документации Apple, но я всегда находил, что она написана таким образом, что читатель является хорошим программистом на Objective-C. Я пытался найти более удобные учебники для начинающих, как вы думаете, смогу ли я реализовать это в своем коде? - gist.github.com/hollance/6328192   -  person rosshump    schedule 17.12.2013


Ответы (2)


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

NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"yourdata.json"];
NSError *e = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:yourdata options:NSJSONWritingPrettyPrinted error:&e];

if (jsonData) {
    [jsonData writeToFile:url.path atomically:YES];
}

Вы также можете сохранить свои данные в виде файла plist. Следующее запишет данные в plist:

NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"yourdata.plist"];
NSError *e = nil;
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:yourdata format:NSPropertyListXMLFormat_v1_0 options:0 error:&e];

if (plistData) {
    [plistData writeToFile:url.path atomically:YES];
}

Списки Plist можно сохранять в двоичном формате или формате XML, и вышеприведенное сохранит их в формате XML, что означает, что XML также будет доступен для чтения в текстовом редакторе. Опять же, это не будет отображаться в виде электронной таблицы. Если вы хотите экспортировать данные в формате CSV, вам, вероятно, придется написать собственный код для их вывода.

person Gavin    schedule 17.12.2013
comment
Хорошо, я попробую оба этих метода и посмотрю, какой из них лучше всего подходит. Где я должен реализовать этот код в методе viewDidLoad в Q4ViewController? Или у него должен быть свой метод? Извините, но я действительно новичок в программировании iOS, спасибо. - person rosshump; 17.12.2013
comment
Вы бы поместили его туда, где логически было бы целесообразно сохранить информацию. Мне нужно посмотреть на ваш код в целом, чтобы понять, где его лучше всего вызывать. Но что касается помещения этого фрагмента кода в отдельный метод, то это имело бы смысл, особенно если вы хотите передать массив или словарь для кодирования в метод, если вы хотите вызывать его в разных местах вашего кода. - person Gavin; 17.12.2013
comment
Это гениально, большое спасибо! Я смог без проблем сохранить его в .plist. Теперь я собираюсь реализовать функцию отправки .plist по электронной почте. Моя единственная проблема сейчас - это формат, который он отображает, т.е. пункт 0, пункт 1 и т. д. Есть ли способ изменить эти значения? Спасибо за вашу помощь! - person rosshump; 17.12.2013
comment
Я пытался отредактировать свой комментарий, но, к сожалению, я оставил его слишком поздно. Моя другая проблема: .plist перезаписывается новым .plist каждый раз, когда анкета заполняется и перезапускается, эта функция удобна, если я собираюсь отправить результаты по электронной почте, но есть ли способ просто добавить новые результаты к тому же .plist файл каждый раз? Потому что в идеале я хотел бы отображать прошлые результаты в UITableView. В данный момент я показываю результаты NSMutableArray, но я хотел бы показать прошлые представления, позволяющие пользователю выбрать один. Должен ли я создать новую тему для этого вопроса? Спасибо. - person rosshump; 17.12.2013
comment
Наверное. Я бы сказал, что это новый вопрос, потому что он касается чтения файла plist, а не его записи. - person Gavin; 17.12.2013
comment
привет. Можете ли вы предоставить некоторые способы получения данных из этого файла json/plist? Спасибо - person famfamfam; 22.02.2018

Вы можете использовать стандартный протокол NSCoding для сохранения данных, но в этом случае вы не сможете прочитать их в Excel. Или вы можете сохранить его в xml. Или вы можете вручную создать файл csv (значения, разделенные запятыми) и открыть его в любом месте. Реализация в любом случае зависит от вас :)

person Ievgenii    schedule 17.12.2013