Good day, читатели!
Решил разбить эту статью на две части – первая будет про НЭП Новую Файловую Политику и чистку любимой папки Documents, т.е. полезную iOS-девелоперу информацию (вроде на хабре про это ещё не писали). Информация очень полезная, если вы хотите сберечь нервы, время и деньги при залитии обновления / нового приложения на AppStore, так что рекомендую к чтению всем-всем-всем.
Во второй я расскажу про войну с первой линией техподдержки Эппла и синдром вахтёра, но она носит скорее повествовательный характер и её читать не нужно.
Куда теперь записывать файлы?
В любом учебнике / мануале по iOS 3.x-4.x было английским по белому написано – создайте метод наподобие+ (NSString *) pathForDocuments
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [paths objectAtIndex:0];
}
И пишите туда всё – базу, кэш, картинки, скачанные из интернета – в общем всё что заблагорассудится. С введением сервиса iCloud в iOS 5.0 Apple изменила политику в связи с тем, что и iTunes, и iCloud делают полные бэкапы папки Documents
Поясню на примере – например, вы купили своему любимому чаду айфончик и, после долгих слёз, угроз и уговоров, айпад. Счастливый ребёнок сразу установил Angry Birds, да вот незадача – прошёл в школе под партой целых два пакета уровней, а на домашнем айпаде, с которым так чудно валяться под одеялом после отбоя пока папа не видит, нужно всё проходить заново.
Но не бойся, малыш! Чудо-iCould засинхронизировал твою папку Documents, и теперь свежеоткрытые Golden Eggs доступны тебе и под одеялом! Теперь и в формате HD.
Если ваше приложение работает именно по такому принципу, то ничего менять не нужно. Как и сказано в правилах Apple, контент, созданный самим пользователем (user-generated content) является самым святым и православным типом данных и подлежит синхронизации. Но рассмотрим другой пример.
Такое явление, в частности, наблюдается со словарями Lingvo. По заповедям Apple, тот контект, который может быть программно воссоздан либо скачан заново из интернета, помещать в Documents категорически запрещено (за это полагается Reject). Вместо этого, их следует помещать в Library/Caches, откуда система, в случае нехватки места на диске, их тут же снесёт. Сценарий встречается чаще чем вы можете подумать – стоит закачать пару немецких HD фильмов на iPad для вечернего просмотра с любимой, и немецко-французского словаря как не бывало – придётся перекачивать его по 3G по дороге на работу. В метро.
Естественно, разработчики стали возмущаться – пользователь не захочет пользоваться программой, из которой исчезает контент, накачанный дорогими мегабайтами сотового тарифа. Для этого, уже в 5.0.1, Apple добавила аттрибут Do Not Backup – стоит поставить такой на любой файл или папку в Documents, и iCloud вместе с iTunes будут их игнорировать. Вместе с тем, система не будет иметь права удалить их при нехватке свободного места, т.е. всё останется как по старинке. В коде это выглядит так (взято из официального источника):#include
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
НО – существенное но – необходимость их хранения в Documents ещё нужно будет доказать при ревью (пункт про то, что без этих файлов рушится user experience приложения, нуждается в основаниях). Конечно, ревьюверы доколупливаются не ко всем – я был свидетелем, как 2 недели назад они пропустили приложение, которое нарушало их правила, но и размер файлов был мизерным – не более десяти килобайт. Если же вашему приложению нужны десятки, а то и сотни мегабайт – ждите придирок и нападок, даже если вы делаете update, а не заливаете приложение с нуля. Хотя бывает, что после пяти и более-дневного ожидания Apple вообще не запускает ваше приложение перед аппрувом – спасибо Эпплу за это.
На этом всё по полезной информации, обязательно прочитайте официальные правила – там немного букв, но они позволят сэкономить вам много нервов.
Как нужно было сделать
Но всех проблем можно было бы избежать, если бы они просто добавили новую папку в файловую систему, не затронув при этом старых. Например, создали бы папку synchronized, где повелели бы размещать сохранённые игры, favorite pages читалок и креденшиалы к почте – и все, кому надо, дописали бы нужные пару методов. Вот при Стиве…
Как бороться с Reject-ом
Это будет полезно только тем, кто уже столкнулся с данной проблемой. Итак, ранним утром прихожу на работу и вижу – приложение зареджектили. Почитал святые скрижали, на которых ссылался ревьювер — и правда, нарушили заповеди №1 и №2. Но, прочитав №4, я понимаю, что лазейка всё-таки есть. Пара минут на дописывание кода, 2 часа на тестинг QA, и мы ресабмитнули приложение, сопроводив его комментарием о том, что наши файлы нужны “ for proper functioning of your app or because customers expect it to be available during offline use”. Что, кстати, являлось чистой правдой.
Через два дня второй реджект, приходит ответ от Apple в стиле:
Thank you for your reply.
//цитата из второго пункта про недопустимость не-user-generated содержания
Заказчик анально обеспокоился, но я решил взять их нахрапом – расписал подробно, на пол-страницы, назначение каждого файла, каждой мелкой папочки, попросил ссылаться не на пункт 2, но на пункт 4. Заказчик ещё добавил от себя, через 3 дня новый ответ:
Thank you for your reply.
//цитата из второго пункта про недопустимость не-user-generated содержания
Заказчик впал в панику, каждый день по 3 раза я стал получать письма содержания:
I believe in my heart that you don't take it lightly.
But your refusal to take other actions is puzzling, disappointing and frustrating.
Или, ещё лучше,
I'm not going to pay for lost time. And every client will be deducted from such invoices. You leave me no choice.
В общем тыщи их, но суть не в этом.
Учитывая скорость ответов от Apple (раз в 2-3-4 дня), обстановка накалялась. Складывалось впечатление, что ревьювер ниасилил четвёртый пункт скрижалей, остановившись на копипасте первых трёх.
Надо добавить, что писали мы в Resolution Center, описывая нашу ситуацию в разных словах, но каждый раз получали одинаково наплевательский ответ. Не помню точно, кому пришла в голову мысль, но мы написали то же самое, с приаттаченой перепиской, в техническую поддержку, и через 3 дня неожиданно получили апрув.
Прочитав
YAY! WE ARE SO HAPPY AND EXCITED. THANKS FOR ALL YOUR HARD WORK! (EVEN WITH THOSE IDIOTS IN THE REVIEW PROCESS)
я со спокойной душой отправился пить пиво с валерианкой.
Резюме
Всегда читайте обновления в политиках Apple и по возможности следуйте им.
Если ваше приложение содержит в себе какие-нибудь особенности (будь то большой размер sandbox-a, необходимость работы в оффлайне, хитрую оптимизацию) – не пожалейте времени описать всё это в поле “Review Notes” в iTunes connect.
При Reject-е приложения с вопросом сложнее, чем неверное имя приложения, всегда пишите сразу же в службу поддержки – переписка с ревьювером через resolution center является пустой тратой времени. Так и вижу домохозяйку индийского происхождения на том конце интернета.
Удачи вам и вашим приложениям, и да прибудет с вами аппрув!