Обычно, когда вы вносите видимые изменения в объекты UIKit вместо немедленного обновления, они просто помечают себя для внесения этих изменений в будущем, а затем выполняют весь набор изменений в виде пакета в следующий раз, когда вы отказываетесь от основного потока (возвращаясь кrunloop).Это не ошибка или сбой в реализации, на самом деле это обычно то, чего вы неявно ожидаете, потому что вы можете написать такой код:
view.frame = someNewFrame;
view.someOtherProperty = someOtherValue;
И не беспокойтесь, что время от времени представление будет явно приниматьновый кадр, прежде чем принимать другие изменения.Как правило, вы хотите, чтобы вещи, которые вы делаете с представлениями, выглядели атомарными.
Иногда вы сталкиваетесь с ситуацией, как у вас здесь, когда факт, что изменения, которые вы уже запросили, не пришелв действие еще выставлено.frame
и someOtherProperty
вернут свои новые значения в приведенном выше примере, так что вам все равно, вступили ли изменения в силу немедленно или нет, но на основании ваших наблюдений о performSelector:withObject:afterDelay:
кажется вероятным, что вы наткнулись наситуация, когда изменение не претендует на немедленное действие.
EAGLView
трудно диагностировать, потому что на самом деле это не функция UIKit.Это CAEAGLLayer
, на котором он построен, но EAGLView
- это просто имя, которое Apple приняла для пользовательского подкласса UIView, построенного на CAEAGLLayer
в различных примерах проектов.Они не были единообразны в отношении интерфейса или реализации EAGLView
в своих примерах, но, вероятно, я бы сказал, что, вероятно, он создает объект буфера фрейма OpenGL (то есть то, что OpenGL использует для хранения чисел, связанных спикселей, что позволяет glReadPixels
работать), только когда его просят выложить, и он не выкладывается, пока UIKit не попросит его это сделать.И это не до тех пор, пока вы не зашли в runloop.
Этот диагноз можно подтвердить, проверив код EAGLView
, который у вас есть.Если есть несколько вызовов таких вещей, как glGenFramebuffers
, которые срабатывают в результате layoutSubviews
, drawRect
или какого-либо другого метода, который не вызывается напрямую соответствующим init
, тогда это подтверждается.
Предполагая, что этот диагноз верен, вы можете адаптировать EAGLView
, но я думаю, что, вероятно, лучшее решение - просто придерживаться performSelector:withObject:afterDelay:0
.Это не условие гонки, так что решение не является ни малейшим ошибочным или ненадежным, это всего лишь несколько окольный способ сказать "пусть UIKit догнать все эти инструкции, учитывая, что я знаю, что позволит EAGLViewвойти в осмысленное состояние, а затем продолжить с моими вещами ".