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

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

Данная проблема проверялась на 4 вариантах запуска:
Xcode 6.4 + 8.1 проявляется
Xcode 6.4 + 8.3 проявляется
Xcode 7.0 + 8.3 проявляется
Xcode 7.0 + 9.0 не проявляется

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

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

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

И теперь пробуем слегка мотнуть список вверх.
В результате он застывает в такой позиции, в данном случае на 28 секунд:
image

Ну что ж, посмотрим, что заставляет его задуматься.
Ставим на паузу и смотрим backtrace:
image

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

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

Если точнее, то вызывает его метод _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.

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

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

UPD. В комментариях подсказали более лаконичный способ:

Method m = class_getInstanceMethod(objc_lookUpClass("UIPickerTableView"), sel_getUid("_playClickIfNecessary"));
method_setImplementation(m, imp_implementationWithBlock(^(id _self){}));