Как стать автором
Обновить

Комментарии 63

Странно что вам раньше это в голову не пришло.
Я правда не особо пишу под iOS, но вообще проверять идентичность бинарников при трудноуловимых, но не-плавающих багах это фактически правило для меня :)
Спасибо за совет, теперь и я так же делать буду! Меня ввело в заблуждение то, что не показывалась одна вьюшка, а не всё приложение.
Я думаю что это ваш долг, разобраться. Даже если за натыкивание ассертами не платят. Я всегда уковыриваю баги до прояснения ситуации. Иначе спать не могу.
Вы меня мотивировали! Завтра останусь после работы и расставлю ассерты по всем проблемным местам, как только найду — допишу UPD в статью! За этим офшором и аутсорсингом иногда забываешь о программистской этике…
где можно почитать? :)
сарказм?
Да нет, как всегда появились «более важные дела»…
У меня тоже возникла проблема при запуске моего приложения, написанного на SDK 4.2 под iOS 5.0.1, оно тупо падало, причем ровно один раз (почему-то происходил Segmentation Fault и приходил сигнал SIG_TERM приложению и никакого внятного, хоть сколь нибудь объясняющего ситуацию, стектрейса). Пришлось качать Xcode 4.2 с SDK 5, проект тоже не собрался с первого раза :) (пришлось ВООБЩЕ все cpp переименовывать в mm, чтобы в хедерах использовать NS классы). В итоге все равно падало один раз (удавалось воспроизводить только при перепрошивке девайса), в итоге я дошаманился, что не смог больше уронить, залил как есть. Ждемс чего скажет эппл. К чему я это, если раздобудешь мак (или хакинтош, или еще чего), с радостью предоставлю тебе код для ковыряния.
P.S. с меня пиво, в случае успеха ;)
После нового года может и гляну, пока нет особо времени.
Мистический баг. Я думаю вполне нормально, что для того чтобы все хорошо работало в iOS 5 надо компилировать под 5 SDK.

У нас, так же, бывали мистические проблемы после компиляции для 5 SDK. Так некоторые анимации работали не правильно, причем только под iPhone 3G с iOS 4. Как оказалось позже баг проявлялся только при включенной оптимизации, что нас удивило, так как на остальных моделях и прошивках было все хорошо.
То же самое, но на другом проекте — анимации на iPhone 3G с iOS 4.2.1, когда билд компилился из-под SDK 5.0. Похоже, мой старичок 3G доживает свой век :( RIP, iPhone 3G!
У меня тоже 3G и похоже действительно доживает. Для четверки так и не вышло апдейта с новыми таймзонами имени Медведева? Пришлось отключить автосинхронизацию часов. В некоторых приложениях скачет время (свежие твиты показываются «час назад») и прочее…

А жаль, вполне устраивал.
это только при использовании llvm для arm6, довольно известный баг.
Возможно известный, просто появился он только с переходом на iOS 5 SDK. До этого команда тестеров и собственно юзеры не жаловались.
При использовании Release для armv6 (llvm и GCC).
Недавно сам с таким столкнулся
Да, llvm подгоняте ништяков. Недавно получил эррор:
Unknown type name 'BOOL'; did you mean 'BOOL'?

Вылечилось откатом на старый gcc, при чем это документированный баг, в новой версии обещали пофиксить.
«Мысль о том, что платная программа не выполняет 100% своих функций, хоть и выполняет 99,9%, будоражит мозг буржуя, лишает его сна и вкуса к жизни.»
)))
В письмах он подолгу описывает чувство невообразимого frustrating, когда видит белый экран вместо данных, за которые его компания заплатила $0,099, черпая вдохновение у Хэмингуэя. Please fix this ASAP!!!, we don’t know what we are paying for!!!, I don’t want to pay for something that does not work properly!!!........."
)))
«Мы сделали всё, что могли, даже сделали больше. Тестили под дебагом все билды за последние месяцы, включая продакшн и продакшн Release Candidate. Ставили разное время и разные локали.»
))))))))))))
«Наш QA беспомощно пожимал плечами, мы через день (потому что всё-таки нужно спать и иногда вовремя уходить с работы) дебажили по TeamViewer девайсы заказчика – под дебагером всё работало идеально. Но как только я собирал им очередной Ad-Hoc, всё продолжалось по новой.»
)))
"… Что именно изменила Эппл, так и осталось загадкой, т.к. дебажить девайс с SDK 5 из xCode c SDK 4 нельзя....."
)))
«Всё же я считаю, что Apple делает правильно, забивая каждый новый релиз на все старые версии»
))) и в добавок в корне не верно

Мой вывод следующий: не будьте инертны и безразличны, читайте доки доступные на developer.apple.com/devcenter/ios/index.action (особенно новые, после выхода каждой очередной iOS) и вы сведете получение подобных проблем к минимуму.
Я бы не сказал, что я вёл себя инертно. На самом деле не очень приятно получать много плохих писем от end-кастомеров, заказчиков и руководства, так что если бы я мог прекратить это и пофиксить проблему — я бы сделал это тут же.

Также не вижу, как документация (тем более ссылка на её корневой каталог) могла помочь мне в решении данной проблемы. Но спасибо за небезразличие!
На самом деле я не комментировал каждый сомнительный опус, т.к. не хотел вдаваться в бессмысленные дискуссии))) Я хотел лишь подчеркнуть, что со многим не согласен, либо некоторые высказывания спорны и не отражают реальность.

По части писем вы себе навязываете, я подчеркивал то, что вы сидите на хрен знает какой старой среде разработки — иммея ввиду высказывание о инертности (мне тоже новая xCode не по нраву была, но опыт поддал волшебный пинок по этой части, что помогло предупредить многие проблемы). Хотел также подчеркнуть чтение документации в частности изменений, которые не просто так пишутся с выходом новой SDK, что помогло бы иметь хотя бы минимальный багаж знаний о том что apple неплохо поработало над компилятором в iOS5 (о котором кстати упоминалось, хотя может вру еще при выходе 4-ки) да не только в принципе по этой части, если уж говорить об мажорных изменениях. Во всяком случае это точно подвигло бы на размышления при поиске логических предпосылок для возникновения бага. А не пальцем в небо меняя локали (зная ее реализацию, довольно странно предполагать, что там что-то не так) + про смену времени ситуация аналогичная. А ссылку я привел не как руководство к решению вашей проблемы, а просто в качестве указателя на официальную документацию, которая без проблем доступна и всегда актуальна.

На самом деле платформа имеет достаточно малый порог вхождения и не устанавливает четкие рамки. Скажем так мы сильно обнаглели и о многом не заботимся, что позволяет нам вот в таких случая зацикливаться на одном и буквально пытаться попасть пальцем в небо. Это и со мной случается, чего скрывать, но объективного и правильного способа и тем более подмены правильности решений и отгребания в случае их несоблюдений это не отменяет.
Ну именно по-этому Apple выпускает бета версии прошивок. Другое дело когда ты испольдуешь SDK 5.0, ставишь таргет 3.1.3, а XCode тебе не слова не говорит, что половина API которые ты используешь не существует в 3.1.3. Впрочем все это делается, чтобы мотивировать кодеров делать приложения с использованием новых API тем самым мотивируя пользователей покупать новые айфоны.
Устаревшие методы всегда видны в «варнингах». А чтобы понять время жизни метода достаточно заглянуть в заголовок из «фрейморка», где он описывается. Нету тут никакого волшебства!
Устаревшие, но не новый. Я использовал метод который появился только в 4.x, в эмулятор все работало, а как только залил на девайс с iOS 3.1.3 приложение падало при вызове этого метода.
Deployment target — не более чем формальное ограничение, не позволяющее приложению AppStore устанавливать билд на девайс, не подпадающий под ограничение. Оно ничего не говорит компилятору.

В отличие от Base SDK, которая решает всё — т.е. откуда конкретно будут линковаться при сборке SDK-шные функции.
Во-первых не «эмулятор», а «симулятор». И не поверю, что на симуляторе 3.1 работало. Но завтра на работе проверю. Вы ведь правильно понимаете, под какой системой необходимо дебажить в случае если вы выставляете Deploymet Target SDK ниже версии Base SDK? И правильно понимаете, что такое обратная совместимость? как бы наличие нового метода, и отсутсвие в старом sdk по моему логически понятно, и не включает в себя понятие «обратной совместимости». А вот когда Apple выкашивает старый метод не сразу, а спустя n-ное количество новых SDK и через одну мажорную версию это уже другое. Не так ли?
Да, да, симулятор. А с каких пор XCode имеет в наличии смулятор 3.1 при отсуствии SDK 3.1?

> И правильно понимаете, что такое обратная совместимость? как бы наличие нового метода, и отсутсвие в старом sdk по моему логически понятно, и не включает в себя понятие «обратной совместимости».

Да. Я говорю, что мне не понравилось, что XCode весь такой умный, а проверить, что метод появился после Target SDK не смог. Назвали бы это другими словами (вы же любите подбирать слова) у меня не было бы вопросов.

> А вот когда Apple выкашивает старый метод не сразу, а спустя n-ное количество новых SDK и через одну мажорную версию это уже другое. Не так ли?

Это тут причем? У меня нет никаких проблем с обратной совместимостью, мне поведение XCode не понравилось.
> Да, да, симулятор. А с каких пор XCode имеет в наличии смулятор 3.1 при отсуствии SDK 3.1?

может и не имеет, на самом деле не помню. Уже пол года как отказались от поддержки 3 и не помню о наличии конкретных версии после первой мажорной. Не пытайтесь уходить в сторону, вопрос лишь в том под какой версией вы дебажите при установке нижнего порога и того, что вы якобы чего можете не заметить. + глобальные брекпоинты для приложения рулят, что отчасти заменяет отсутствие необходимого вам функционала.

> Да. Я говорю, что мне не понравилось, что XCode весь такой умный, а проверить, что метод появился после Target SDK не смог.

По части умного xCode))). Так не такой уж он и умный, во всяком случае не умнее продуктов от jetbrains, VS или того же эклипса. Довольно долго очень близко не работал с другими IDE но на моей памяти всегда совместимость со старыми версиями перекладывалась по большей части на разработчика и QA, нежели на среду.

>Это тут причем? У меня нет никаких проблем с обратной совместимостью, мне поведение XCode не понравилось.

Не от вас вычитал кусок текста, либо просто не понял, уже не помню откуда взял. Извините, тяжелый день;)
> может и не имеет, на самом деле не помню. Уже пол года как отказались от поддержки 3 и не помню о наличии конкретных версии после первой мажорной. Не пытайтесь уходить в сторону, вопрос лишь в том под какой версией вы дебажите при установке нижнего порога и того, что вы якобы чего можете не заметить. + глобальные брекпоинты для приложения рулят, что отчасти заменяет отсутствие необходимого вам функционала.

Нет, не имеет. Там даже старые версии SDK выпиливаются. Не ухожу я в сторону, я просто не говорил, что дебажил в эмуляторе под 3.1.3 :) Я понимаю, что косяк мой и только мой. Просто как-то странно выглядит деприкейшен ворнинги от отсуствие проверки по Target SDK. (нет, я не потратил неделю на поиск проблемы, я просто открыл тут же документацию к методы и увидел, что появился он только в 4.какая-то там)

> По части умного xCode))). Так не такой уж он и умный, во всяком случае не умнее продуктов от jetbrains, VS или того же эклипса. Довольно долго очень близко не работал с другими IDE но на моей памяти всегда совместимость со старыми версиями перекладывалась по большей части на разработчика и QA, нежели на среду.

Статический анализ у него божественный (да, я знаю это не заслуга Xcode, но apple стоит за работкой же). Однако, Xcode быстрее чем любая JVM IDE, мне нравится больше чем VS. Не смотрел IDE для iOS от JetBrains, но если она так же хороша как и WebStorm (которая кстати через чур завязана на классический javascript и совсем не помогла мне при работке под SproutCore.
А я понять не могу, как то, что на разработчиков приложений перекладывают написание хард фиксов и хитроумных «комбинаций» вместо того, чтобы сделать это через удобный механизм deprecated в самой ОСи — это при том, что на рынке всегда болтаются минимум устройства 2 разных поколений (особенно учитывая, что старые модели не сразу получают обновление версии, а те же iPOD'ы — вообще никогда), в общем, как такая ситуация может выглядеть «правильной».
> (особенно учитывая, что старые модели не сразу получают обновление версии, а те же iPOD'ы — вообще никогда), в общем, как такая ситуация может выглядеть «правильной».
Say what?

Они или получают обновление сразу в один день в один миг, или не получают совсем (о чем заранее известно) Вы кажется перепутали ситуацию с андроидом. Единственная ситуация когда владелец не обновляет устройство это окгда ему нужен jailbreak или unlock.
просто нужно тестировать и на последних прошивках! Тим лид еще, блин… зря потратил время читая этот пост, думал что узнаю что-то нового…

у меня случаев с несовместимостью много было. К примеру, если кто не знает, то в 5-й MPMoviePlayer может тупо остановиться во время воспроизведения короткого ролика. И его воспроизведение длится дольше чем duration.
Напишите 100 раз маркером на доске — я буду внимательно читать ваш пост, iago, перед тем как постить в комментах ерунду. Мы, естественно, тестировали на последних прошивках, только приложение устанавливали из нового xCode и SDK, т.к. из старого на новый девайс не поставишь. В общем перечитайте ещё раз
какой же вы тимлид, если пользуетесь уже устаревшим сдк и версией ос…
очень бородатый тимлид
Идея собирать с поддержкой 4.3 на SDK 4.3 казалась мне тогда логичной… но учту опыт.

А вам, я вижу, как и многим на хабре, чем-то не угодили тим-лиды и ПМ-ы? По любому вопросу пытаются доказать профнепригодность.
А потом еще зря потратили время на написание своего комментария ;-)
это из-за недовольства :)
вы правы, все последующие сообщения буду игнорировать, чтоб не тратить время попусту. ;)
А еще удручает тот факт, что в АппСторе нет фильтрации по версии iOS. Вот у меня первый айпод тач, например, а большая часть приложений не поддерживается. Это ещё ладно, но зачем, зачем они отображаются в АппСторе?
Чтобы вы кусали себе локти и купили новый айпад ;)
Да вот в том-то и дело, что новый айпад я себе не куплю, зато приложения покупать стал меньше. Потому что задолбала эта угадайка.
Хороший пост, у нас кстати недавно была тоже проблема при переходе на 5 версию оси.
Проблема была следующего характера — в одном из контролов в навигационной панели висела сегментированная вьюшка, переключение которой приводило к некоторым действиям в логике приложения. Соответственно на переключение его значения был подвешен таргет, и перед самым началом работы приложения контролу задавалось текущее значение выбранного сегмента, чтобы сделать преднастройку параметров приложения. Выглядело это грубо говоря следующим образом:

UISegmentedControl* control = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"First", @"Second", nil]];
[control addTarget:self action:@selector(controlChanged) forControlEvents:UIControlEventValueChanged];
[control setSelectedSegmentIndex:1];


Так вот, на четверке этот код замечательно работает, а на 5 оси вызов сообщения @selector(setSelectedSegmentIndex:) перестал приводить к вызову привязанного таргета. Лечили тупым вызовом самого привязанного селектора, дописав такую строчку:
[self controlChanged];
Была ситуация с переходом на XCode 4.2 c точностью до наоборот. Все отлично работало на всех прошивках в старом XCode. Компилировали и дебажили билды под новым — тоже все ок. Отправили ad-hoc на тестирование (хорошо, что не по старинке, просто загрузить да девайс билд) — приходит фидбек что вообще не работает ничего, даже тачи глючат. Вывожу на экран координаты тача — x и y совпадают, причем совпадают еще до моей какой-либо обработки. Выяснилось в итоге, что это срабатывает оптимизация нового компилятора. Поменял компилятор на gcc или отключил оптимизацию — все ок. Потому тут все не так однозначно. Мануалы мануалами а опыт опытом.
А какой стоял вместо gcc, если не секрет?
Наверное LLVM 3.0
У меня подобные проблемы были когда я напортачил в методе viewDidUnload. Не релизил созданную кодом вьюшку (только в dealloc релизил). В итоге когда приходил memory warning — начинались чудеса )
Есть такая особенность, но это особо не связано с SDK и обратной совместимостью :) А так да, лик из ниоткуда. Я тоже помню года полтора назад пол-дня потратил. На мой взгляд, само название метода неудачное — по аналогии с viewDidLoad называли, но играет совсем не противоположную роль. Зато на собеседованиях хорошо спрашивать — и 50% «Senior iOS developer'ов» сыпятся на вопросе когда этот метод вызывается и что в нём надо делать :)
Скорее от lifecycle отталкивались, причем тут назначение противоположное? Для таких методов (которых предостаточно для контроллера) все различное по назначение, хоть в названии и присутствует схожесть.
Ага, только viewDidLoad вызывается каждый раз, а viewDidUnload — только при Memory Warning. Может хватит уже троллить по любому поводу? Надоел, честное слово!
))) хорошо не буду вас троллить, раз вы считаете что я вас обижаю тем что не согласен со многих. А по поводу viewDidUnload и вызов только при Memory Warning вот ссылка: stackoverflow.com/questions/1158788/when-should-i-release-objects-in-voidviewdidunload-rather-than-in-dealloc (тут более ли менее можно вычитать почему и как, что можно проверить на простом тестовом примере, попробуйте)) )
надеюсь вам хватит ума понять, что вы говорите о частном случае как о единственном возможном.
Что вы хотите этим сказать, тем более в такой грубой форме. В линке на StackOverflow приводится «It is called during low-memory conditions when the view controller needs to release its view and any objects associated with that view to free up memory.», цитата из SDK. ЧТД, о чём я и говорил. Всё, не кормлю, итак жирный стал.
У меня каких-то глобальных проблем не возникало, но на всякий случай все свои программы перевел на ARC.
и отказались от поддержки 4.х, зачем?
нет, он отлично компилится на 4.x, проверяю на iPhone 4S, 4(4.3.3) и 3GS(4.2.1)
А нельзя втыкать в одно приложения разные билды для разных операционок?
Чтобы был какой-нибудь маленький загрузчик, ну starter типа, а он проверяет версию операционки и запускает уже подходящий бинарник или грузит правильную либу. Так можно было бы минимальными усилиями обеспечить совместимость приложения со всеми версиями ОС.
оно и так совместимо со всеми версиями ОС, просто когда выходит новая ОС, не сразу становится понятно что в ней отвалилось, особенно если баг проявляется далеко не у всех.
Вопрос не в этом.
Вот есть у вас приложения для 3.1.3, а вышла уже 5.0.1, и вы хотите использовать новые плюшки из SDK5 — оставляете старую версию приложения нетронутой, для владельцев старых аппаратов, которых лишили апдейта на iOS5, а новые плюшки делаете в новой версии программы. Потом засовываете обе версии в одно приложение и в зависимости от версии iOS запускаете подходящий бинарник.
Возможно ли такое в принципе?
Ну, примерно как в Windows можно было в один exe-файл засунуть консольное приложение для DOS и гуёвое (ну или тоже консольное) для винды. Или как у Apple был формат исполняемых файлов Universal Binaries — по сути два независимо скомпилированных бинарника в одном приложении.
Можно внутри кода проверить версию ОС, собственно так сейчас костыли и пишутся, вот например надо вам сделать кастомный навигейшен бар, для иОС 4 вы просто переопределяете метод drawRect, и рисуете там что угодно, но в иОС 5, это уже работать не будет. Потому что Аппл теперь для этих задач добавили специальные методы, вот и приходится еще для иОС 5 писать свою реализацию.
т.е. если пишется приложение с base sdk 4.3, где юзается drawRect, то оно не запустится на 5?
запустится, но т.к. в иОС бекграунд навигейшен бара меняется по другому, drawRect не будет запущен, и в приложение под 5.0 будет показываться дефолтный бекграунд.
> сделать кастомный навигейшен бар, для иОС 4 вы просто переопределяете метод drawRect, и рисуете там что угодно, но в иОС 5, это уже работать не будет. Потому что Аппл теперь для этих задач добавили специальные методы, вот и приходится еще для иОС 5 писать свою реализацию.

Не совсем так: вкратце Вы «переопределяли» при помощи Categories метод drawRect, а в iO5 было изменено поведение Categories, после чего у вас все сломалось под iOS5. А то что для работы с UINavigationBar добавили дополнительные методы это дело уже третье, причем при достаточно более сложном представления они не совсем и помогают.

Поэтому более правильно в таком случае вернуть поведение Categories которое Вы скорее всего использовали не только для бара, и вставить один кастыль нежели отдельно на каждый момент, т.е. подправить классы категорий в которых идет упор на переопределение методов. Сделать это можно допустим так:

добавляем класс (к примеру): @interface UINavigationBarCustom: UINavigationBar в имплементации указываем переопределяемый метод вашего класса который вы пытались расширить через Category, в нашем случае это drawRect. Старый класс категории перейменовываем допустим в UINavigationBar+iOS5Support.h и добавляем в него метод:
+ (Class)class {
return NSClassFromString(@«UINavigationBarCustom»);
}
(используемые именования подходят для меня, но скорее всего будут не подходить вам в зависимости от реализации + описание почему это работает для обоих версий опускаю) Таким образом мы повторили старое поведение для категории, несколько изменив ее и добавив дополнительный класс (хотя и это можно вынести в один). Таким образом вставив один костыль, мы решили все проблемы связанные с изменениями в поведении Categories, нежели…

Пользуйтесь, может кому пригодится)
торт!
Первый же параграф под заголовком «Решение» раскрывает, возможно, одну из первопричин возникновения самой ситуации: несколько… скажем так, «необычный» подход тимлида к среде разработки и билду бинарников.
Отличная статья! Большое спасибо автору!
Спасибо! Очень рад что помогло :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории