Как Убрать Зависания Uipickerview В Симуляторе Ios

Время от времени замечаю, что происходят зависания при попытке выбрать элемент в UIPickerView в симуляторе.

Но настолько, что теперь появились тормоза, смотреть стало невыносимо: смена выбранного элемента в «барабане» может занять до минуты, в течение которой интерфейс ни на что не реагирует. Возможно это ошибка бета-версий.

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

Данная проблема тестировалась на 4-х вариантах запуска: Хкод 6.4 + 8.1 проявляется Хкод 6.4 + 8.3 проявляется Хкод 7.0 + 8.3 проявляется Хкод 7.0 + 9.0 не появляется Это говорит о том, что есть какое-то небольшое несоответствие в работе версий симулятора, что в данном случае очень напрягает вариант проявления.

Попробуем исправить проблему.

Запустим довольно простой проект с добавленным «барабаном»:



Как Убрать Зависания Uipickerview В Симуляторе Ios

А теперь попробуем немного продвинуть список вверх.

В результате он замирает в таком положении, в данном случае на 28 секунд:



Как Убрать Зависания Uipickerview В Симуляторе Ios

Что ж, посмотрим, что заставляет его думать.

Сделайте паузу и посмотрите обратную трассировку:



Как Убрать Зависания Uipickerview В Симуляторе Ios

Среди виновников торжества можно проследить АудиоУслугиPlaySystemSound .

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

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

Попробуем отключить его и здесь.

Он вызывается изнутри системы, поэтому отключить его напрямую, конечно, нельзя.

Но можно попробовать разорвать цепочку до него чуть выше.

Точнее, он вызывает свой метод _playClickIfNecessary .

Глядя на название, рискну предположить, что этот метод не делает ничего, кроме воспроизведения звука.

Остается только заменить его реализацию на свою, которая просто ничего не делает. Для примера попробуем создать то, что нам нужно, во время загрузки приложения.

Например, внутри AppDelegate.

 
  #if TARGET_IPHONE_SIMULATOR

- (void)UIPickerTableView__playClickIfNecessary

{

// nothing to do

}

#endif

+ (void)initialize

{

# if TARGET_IPHONE_SIMULATOR

Class srcClass = self;

Class dstClass = NSClassFromString(@"UIPickerTableView");

if (srcClass && dstClass) {

SEL srcSelector = NSSelectorFromString(@"UIPickerTableView__playClickIfNecessary");

SEL dstSelector = NSSelectorFromString(@"_playClickIfNecessary");

Method srcMethod = class_getInstanceMethod(srcClass, srcSelector);

Method dstMethod = class_getInstanceMethod(dstClass, dstSelector);

method_exchangeImplementations(srcMethod, dstMethod);

}

# endif

}



Попробовал сделать замену через категорию, но не получилось:

— через таблицу — потому что ее реализация покрыта UIPickerTableView;

— через UIPickerTableView, потому что у меня не получилось правильно импортировать скрытый API.

В любом случае не столь важно, как заменяется реализация.

Главное, что после замены все теперь работает без тормозов и зависаний, что бесконечно приятно.

Однако кто-то наверняка знает более лаконичный способ избавиться от проблемы, тогда буду очень рад добавить в комментариях.

Потому что за полчаса я не смог найти в Гугле ничего толкового.

УПД.

Комментарии предложили более краткий способ: Method m = class_getInstanceMethod(objc_lookUpClass("UIPickerTableView"), sel_getUid("_playClickIfNecessary")); method_setImplementation(m, imp_implementationWithBlock(^(id _self){})); Теги: #UIPickerView #Разработка для iOS

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2013-01-11 13:40:32
Баллов опыта: 548
Всего постов на сайте: 6
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.