Новая файловая политика iOS 5 и история реджекта по-вахтёрски



    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, да вот незадача – прошёл в школе под партой целых два пакета уровней, а на домашнем айпаде, с которым так чудно валяться под одеялом после отбоя пока папа не видит, нужно всё проходить заново.

    Но не бойся, малыш! Чудо-iCloud засинхронизировал твою папку 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 <sys/xattr.h>
    - (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 является пустой тратой времени. Так и вижу домохозяйку индийского происхождения на том конце интернета.
    Удачи вам и вашим приложениям, и да прибудет с вами аппрув!
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 32
    • 0
      C iOS 3.2 появился флаг UIFileSharingEnabled в info.plist, который и говорил iTunes о необходимости бэкапа папки Documents. Но мне тоже непонятно, зачем было менять этот механизм — кому было надо, тот пользовался.
    • +7
      Идиотизм, по другому не назовешь.
      Если пользователь не обновится с 5.0 на 5.0.1 он обязательно оставит негативный отзыв о приложении.
      А где, например, хранить базу данных для приложения в 5.0? В кэшах, чтобы ее оттуда убили?
      Весьма наплевательское отношение, согласен с автором.
      • 0
        Можно узнать откуда такая информация:
        > И пишите туда всё – базу, кэш, картинки, скачанные из интернета – в общем всё что заблагорассудится.
        Я пишу под айфон с первого публичного SDK и четко помню про папки Documents, Library и Caches из официальной доки.
        • +5
          >четко помню про папки Documents, Library и Caches из официальной доки.
          Я даже рад такому фашизму со стороны Эппла — Android за полгода насоздавал мне на SD-карте сорок папок в корне, и, кроме пары папок — одной со сделанными мною фотками и другой, в которую смотрит mp3-плеер, я не знаю, нужны ли они операционной системе или каким-то приложениям, кэш ли это, временные файлы или важная информация, от удаления которой перестанет работать какое-нибудь приложение.

          Теперь бы ещё прикрутили пользовательскую настройку для программ от не читавших спеки к iOS5 программистов и сохраняющих скачанные карты в Caches — что вполне логично, чтобы можно было явно пометить приложение как неприкасаемое для автоматической очистки.
        • 0
          Вы же не станете спорить что раньше никому в голову не могло прийти ревьювить Documents?
          • –1
            >Но всех проблем можно было бы избежать, если бы они просто добавили новую папку в файловую систему, не затронув при этом старых. Например, создали бы папку synchronized, где повелели бы размещать сохранённые игры, favorite pages читалок и креденшиалы к почте – и все, кому надо, дописали бы нужные пару методов. Вот при Стиве…
            Скорей всего так было сделано для избежания проблем со старыми приложениями. При текущей реализации с облаком синхронизируются все без исключения app-хи. При предложенной Вами — старые приложения пришлось бы дорабатывать. А ведь есть вероятность, что они уже не поддерживаются (рит.: Зачем они тогда нужны?)
            • +2
              А нафига дорабатывать рабочие вещи?!
              • 0
                Вот именно, что при таком подходе и не надо дорабатывать приложение. Я на личном примере убедился что, подобная синхронизация с iCloud-ом всего и вся- мана небесная. У меня устройство не подключалось к тунцу для синхронизации с момента покупки. Бэкапов не было. Не вдаваясь в суть проблемы, случайно было удалено одно приложение — буквально через несколько минут оно было восстановлено с облака.
                • 0
                  Как подсказывает коллега выше (первым комментарием), кому надо было раньше — тот мог поставить аттрибут UIFileSharingEnabled — естественно все, например, игроделы были в курсе как сделать Documents синхронизируемой.

                  Так что всё же не соглашусь с Вами — лучше добавлять функционал, как они сделали в 3.2/4.0, чем изменять работающие вещи, как они сделали в 5.0-5.1. Что iCloud добро — я полностью согласен, у меня те же сохранённые рекорды все повосстанавливались и пройденные уровни, iPhone 3G iOS 4.2.1. А в пятой оси они лажанулись.
            • +2
              Кстати, да, как пользователь столкнулся. Айпад при синхронизации ругнулся на «нет места», но немецкий кинематограф таки закачал. За счёт карт навигационной программы.

              Причём, процесс сделан совершенно непрозрачно для пользователя — нельзя понять, что именно тебе грохнет синхронизация.
              • +2
                Спасибо за совет про службу поддержку! Как раз актуально, а то уже и надежд почти не осталось, и готовая статья на Хабр лежит всё ещё под сукном из-за глупцов из review team.
                • 0
                  You're welcome! Можете потом ещё и позвонить — но только после того как создадите тикет, без тикета они с вами даже разговаривать не станут
                • +3
                  5.x вообще пичаль, столько радости нам принесла…
                  • +3
                    Я конечно понимаю, что политика «Ось и телефоны наши — что хотим, то и делаем» имеет свои преимущества, но и недостатков у нее много, в основном для разработчиков, а идти на встречу им не хотят. А сейчас еще и пользователей затронуло, если у них не актуальная версия оси (я кстати с выхода 5 даже не смотрел, а есть ли обновления). А виноват в итоге разработчик, хотя ничего поделать в этом случае он не мог.
                    • +2
                      Автоматический бэкап всего в iCloud — отличное бизнес решение. Многие пользователи начнут платить за storage. Ненавязчивый способ приучить пользователей к чему-то новому, да еще и заработать на этом.

                      Когда мы обновляли MapsWithMe, столкнулись ровно с такой же проблемой — оффлайн карты это как бы тоже перезакачиваемый контент, но если он будет удален в неподходящее время…
                      Ссылка на пункт 4 помогла с первого раза.
                      • 0
                        По всей видимости, вы нарвались на толкового ревьювера, а не на особь с иллюстрации к статье :)
                        • +1
                          //offtop

                          Спасибо за отличный эпп — карты очень помогли в Европе (и работают в оффлайне). Всем рекомендую.
                          • 0
                            Мы уже и под Андроидом :)
                          • 0
                            Спасибо за mapswithme!

                            Если не трудно, прикрутите компас к iphone версии чтобы можно было понять в какую сторону смотрит айфон. В родных картах на айфоне такое есть. То есть чтобы маркер, показывающий текущее положение на карте, являлся компасом.
                            • 0
                              Компас должен показывать направление взгляда сектором на кружочке текущего положения. Если у вас не работает (в 3G и iPod компасов нет), напишите, пожалуйста, в личку — попробуем помочь.
                              • 0
                                спасибо за ответ!
                                Оказывается у меня стояла прошлая версия, поставил текущую — компас появился и работает отлично.

                                Спасибо еще раз за приложение!
                          • +1
                            Спасибо за толковую заметку!
                            • 0
                              Всегда рад! Просто очень накипело, выели и мне и заказчику нервы. Погуглил, не нашёл на хабре статьи про это и решил отписаться
                            • +1
                              Когда приложение выходит в апдейт они уже более лояльно относятся к нему на ревью. Хотя бывают косяки. У меня как-то был реджект из-за того что в приложении продавалось > 10 шт in-app purchase по 1$ за раз. Их напрягло что их именно больше 10 шт. Попросили создать отдельный in-app purchase айтем с большей стоимостью, чтобы число приобретенных за раз айтемов не превышало 10-ку… :) Пришлось подчиниться. Благо они детально расписали почему и чем они недовольны.
                              • 0
                                Как на кого нарвёшься… я думаю в любой компании на техподдержке есть нормальные адекватные люди с соответствующим образованием, а есть домохозяйки. Особенно если брать многонациональность штатов, китайцы и индусы в основном атакуют вакансии QA и саппорта, т.е. вакансии с наименьшей ответственностью, и действуют там строго по инструкции. И если вдруг в инструкции встретят противоречие — всё… круто, ты попал на ТВ :)
                              • +1
                                >Такое явление, в частности, наблюдается со словарями Lingvo.

                                Автор прав, с одной поправкой: явление наблюдалось, но уже исправлено.

                                В связи с появлением iCloud и рекомендацией Apple мы сначала из /Documents перенесли словари в /Library/Caches, откуда они у части пользователей с завидным постоянством начали исчезать. Потом появился чудесный хак с Do Not Backup, благодаря которому словари вернулись в /Documents, но текущая версия приложения на 5.0.1+ их уже не теряет.
                                • 0
                                  Спасибо за ценный совет! Так интересно, что на хабре тебе может ответить разработчик Lingvo… с детства пользуют вашим словариком с версии то ли 5, то ли 6, не знаю что бы без него делал!
                                • +1
                                  А можно ли как-нибудь пометить данные чтобы «бэкапить их можно, но сихнронизировать с другими устройствами нельзя».

                                  Например программа — VOIP приложение. Нет смысла синхронизировать историю звонков, сделанных с данного устройства со своими другими девайсами, но бэкапить это хочется.

                                  Как я понимаю, по дефолту файл базы данных будет синхронизироваться с другими устройствами через icloud, верно?
                                  • 0
                                    Всё так, но к сожалению флаг един — действует и на iTunes, и на iCloud.
                                    Apple всё стандартизирует и загоняет в довольно жёсткие рамки. Конечно, в Вашем примере логично было бы ввести два разных флага.
                                  • +1
                                    А дороговато обходится тупость членов Review Team: если так с ними бодаться через техподдержку, то это будет стоить от 50$ за одно обращение, сверх бесплатного лимита 2 в год.
                                    Есть вопросик еще: какую вы выбрали тему для дискуссии с техподдержкой?
                                    • 0
                                      К сожалению, общался сам заказчик (американец), я просто подготавливал для него текст, так что не могу ответить точно.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое