Pull to refresh

Comments 28

Можно и так сказать. В отсутствие нужного public API от Apple приходится искать обходные пути. Если знаете путь прямее — было бы интересно почитать, собственно для того и статью создал. Я в тайне надеюсь, что кто-нибудь найдёт таки в закромах доках Apple нормальный API для отключения этого сдвига и поделится им в комментариях.
Я, к сожалению. вам не советчик (что касается именно iPhone).

Но, как программист, скажу что магическая цифра 7 на девайсах с другим ppi принесет тому, кто будет отлаживать, много спокойных и приятных минут работы.

Вы же знаете, что величина «примерно 3мм», данные о ppi известны. en.wikipedia.org/wiki/List_of_displays_by_pixel_density#Apple_Inc

Забиваете данные о ppi в карту, при определении девайса, находите это смещение.

Дальше delta = 3 / 25.4 * ppi = 0.118110236 * 132 (для ipad) = 15.59 пикселей.

Однако. В рассчетах фейл.

Но это вполне может говорить, что фейл в исходных данных. Значит, это не 3мм, а меньше. А вдруг это смещение адаптивно? Значит, надо пытаться достучаться до apple и выяснить, каково же это смещение.

Я не удивлюсь, что в итоге вы будете первооткрывателем недокументированной функции :)

Хех, а ведь Вы правы. 3 мм это разница между линиями в опыте с Bamboo Paper, т.е. в миллиметрах реальное смещение 1.5, и delta примерно сходится. Ошибся, спасибо.
По поводу магической цифры — специально указал, что это цифра только для конкретного устройства (iPad 1), и нужно дополнительно тестировать на остальных.
Уточню про миллиметры для ясности. Именно на 3 миллиметра будет промахиваться игрок, привыкший к стандартному смещению, если устройство перевернуть (например, для игры черными в шахматах).
Никого не слушайте!!! Свежая сочная фрагментация платформы своими руками в своем же приложении — это же прекрасно!
(ага, когда будут выходить новый яблокодевайсы с другими ppi вам придется добавлять очередные константы и выпускать новую версию)
Вы предлагаете поступить как большинство разработчиков, и никак не учитывать этот сдвиг в приложении? Чтобы пользователь тянул фишку, а она не тянулась/тянулась другая? Нет, я за то, чтобы для известных устройств ввести смещение и сделать интерфейс более удобным для пользователя, пусть это и несёт некоторые накладные расходы для программиста.
А вот на «ну погоди» такого не было!
Зачем залезать на уровень рантаймовой магии, если можно просто обойтись категорией, в которой вы добавите adjustedLocationInView и adjustedPreviousLocationInView? Переправка абсолютно всех вызовов locationInView во всем проекте — очень плохое решение. Эти методы зовутся не так часто, и если вам уж так надо поправить положение UITouch, то лучше потратить 5-10 минут и заменить вызов оригинального метода на свой собственный, там где это надо.
Хороший вопрос. Ответ — для того, чтобы использовать ранее написанные и отлаженные классы и не залезать в их реализацию. Тут надо выбирать: либо мы перелопачиваем весь существующий код и вносим поправки, либо аккуратно в одном месте включаем/отключаем сдвиг. Это во-первых. А во-вторых, я показал всего лишь подход, в реальном проекте сдвиг в UITouch будет включаться/выключаться по требованию, например так:
@interface AdjustedPaintingView:PaintingView
@end
@implementation AdjustedPaintingView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	[UITouch enableAdjustmentsForLocations];
	[super touchesBegan:touches withEvent:event]; 
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
	[UITouch disableAdjustmentsForLocations];
	[super touchesEnded:touches withEvent:event]; 
}
// ...
@end

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

С трудом могу представить ситауцию, в которой locationInView будет вызываться в настолько большом количестве классов, что код предеться «перелопачивать». runtime.h позволяет делать много интересных вещей, но если есть другое решение — лучше воспользоватся им. Если уж правка кода PaintingView совсем невозможна, в вашем случае лучше бует воспользоватся декоратором: завернуть UITouch в NSProxy, форвардить вызовы всех методов к оргинальному объекту, в locationInView и previousLocationInView вносить поправки.
Соглашусь, решение с NSProxy должно быть лучше.
Меня всегда удивляло почему сишники пользуют GL_UINT (WORD16 или подобное), нежели short unsigned int.
Но однажды я понял — класс/тип unsigned short int имеет фатальный недостаток
На самом деле в GL_UINT, QINT16, WORD16 и т.д. есть смысл — у них размер вегда будет одинаков, независимо от архитектуры процессора, чего нельзя сказать о short int. Все эти библиотеки, как правило, начинали писатся до 1999 года, когда в стандарте появился stdint.h с его int8_t, int16_t, int32_t и т.п.
Да, я знаю. Сам сишник. Действительно, ширина int варьируется.

Но ширина short и long постоянная и кросс-платформенная.
Станарт, даже последний, ширину типов не прописывает. Там только сказано, что short
Парсер лох.
В стандарте написано, что short <= int <= long <=long long
Так что кросплатформенность short и long скорее счастливая случайность, чем закономоерность и расчитывать на нее я бы не стал.
Ну надо же. А есть пруф про 3мм? Потому что, судя по вот этому видео — никакого сдвига нет (смотреть с 1:55)
Я думал записать видео, да времени жалко, если честно.
Но вот кадр из видео, что Вы привели:

Обратите внимание, что верхняя горизонтальная линия проходит ближе к краю экрана, чем нижняя. Очень похоже, что это из-за обсуждаемого сдвига. По той же причине в большинстве рисовалок при попытке тонкой линией закрасить весь экран в нижней части остаётся тонкая незакрашенная полоска.
А это не потому что манипулятор робота так установлен? Он же не может в точности повторять очертания экрана. Вы присмотритесь к моментам видео, где крупным планом показано, как он рисует — линии образуются точно в центре соприкосновения манипулятора с экраном.
Я не могу утверждать, по какой причине разница в расстояниях в этом видео.
Но неужели Вы думаете, что в этой статье я решаю несуществующую проблему? :)
Если есть устройство — установите Bamboo Paper и проведите тест из начала статьи.
Не буду обещать, но если будет время, сниму видео замера сдвига в 7 пикселей.
Проверил на Adobe Ideas.
Нужно выбирать самые тонкие линии и самый мелкий масштаб, тогда описанный вами эффект виден. Если линии толщиной в два миллиметра, то они рисуются точно там, где палец касается экрана. На тонких линиях нельзя закрасить нижние пару миллиметров экрана.
Нет, я не утверждаю, что вы решаете несуществующую проблему. Но, возможно, это проблема конкретного приложения или она [проблема] вытекает из каких-то других предпосылок. К сожалению, у меня под рукой нет iPad, чтобы проверить наличие проблемы. Попробую на iPhone 4.
Тут дело в том, что это скорее особенность, которая выливается в проблему лишь в определенных типах приложений, типа шахмат или эрудита. Только что проверил в Scrabble — пытаешься потянуть букву за нижний край, а попадаешь на букву ниже, при этом в привычной ориентации всё нормально.
В тех же рисовалках можно поступить хитрее: разрешить автоповорот, но вращать только меню, т.е. вращение интерфейса компенсировать вращением холста в обратную сторону, создавая ощущение его (холста) неподвижности. Так сделано в том же Adobe Ideas и например в моём LiveSketch HD. При таком подходе направление сдвига будет меняться вместе с поворотом устройства и пользователь сдвиг не заметит.
А вот это очень ценная информация. Честно говоря жаль, т.к. на использовании этой функции завязаны многие интересные библиотеки, например по добавлению АОП в Objective-C.
Не знаете, Apple какую-нибудь альтернативу взамен предоставил?
Вообще это они здорово придумали. На WWDC 2010 в одном из видео этот трюк разрекламировали, а в 2011 в iOS 5 решили запретить. :(
На самом деле смещение координат уже давно было заметно. Особенно это заметно на людях, которые долгое время пользовались android устройствами, и им дают в руки iphone — в кнопку 30 на 30 px с первого раза люди обычно не попадают.
Также всегда была заметно, если у тебя на statusBar висит стандартный обработчик scrollView — topToScroll = YES; прокручивать он начинает уже с нажатия на navigationBar.
Кстати рабочая область кнопок на navigationBar — тоже значительно расширена — и по высоте всегда является высотой navigationBar, а по ширине значительно больше, чем истинный размер кнопки.
Sign up to leave a comment.

Articles