Search
Write a publication
Pull to refresh

Comments 37

...нужно отметить что использование application suspend противоречит лицензии на SDK --- функция не документирована...

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

Альтернативная реализации background приложений была продемонстрирована на WWDC 08.
ну если во время suspend программа остается висеть в памяти, то конечно это плохо. Но если она переносится в своп на флешке, то почему-бы и не использовать?
за вводную в suspend спасибо конечно, но все же стоит делать оговорки, что функция эта не приветствуется разработчиками SDK и что вероятность прохождения процесса сертификации приложения сводится к нулю при использовании таковых, так сказать, хаков.
за статью спасибо.
ну если в Apple будут против суспенда - это будет очень плохо. Вот открыто у меня приложение, и вдруг кто-то мне звонит, так что получается, мое приложение немедленно закроется и когда я его открою придеться все там делать сначала?
Я думаю все-таки будут разрешать делать саспенд для приложений, просто во время него, они будут не в оперативной памяти, а будут перемещатся в своп
судя по всему, реализацией саспенда займутся сами разработчики SDK, сделав что то наподобии hide \ show notify (или startApp, pauseApp) в J2ME, т.е. пользовательское приложение будет уведомляться о том, что его засуспендили и о том, что вернулись к его выполнению. а как себя будет вести телефон и куда он будет запихивать данные - конечного разработчика волновать не будет.
там все уже есть... iPhoneOS при поступлении прерывания, такого как звонок или что-то еще... кидает сообщение о том, что приложение будет закрыто, в этот момент необходимо сохранить информацию о текущем состоянии приложения, а при последующем запуске — восстановиться...
Что это так плохо плюсуют?
Автор, большое спасибо, такие материалы нужны!
Плюс в карму и топику.
>Что это так плохо плюсуют?

да я уже привык. Большинству больше нравиться пообсуждать "почему я использую {вставить любое слово}", как Тёму засуспендили и т.п.
Н-да.
Ну ничего, главное, чтобы ты не опускал руки.
Еще раз большое спасибо.
метод рассчета коэффициентов антиинтуитивен. Если я правильно понял код, то при изначальном касании, скажем, строго на одной горизонтали, у меня получится стартовая разница в 0.05, и если я чууть-чуть один палец с этой горизонтали сдвину, вертикальный размер логотипа "выстрелит" в неприлично большие значения.

предлагаю такие варианты:

Простой: если стартовая разница по оси меньше, скажем, пятой части экрана, то считать её этой самой пятой частью.
Компромиссный: сделать пропорциональное масштабирование. текущее расстойние между пальцами делим на стартовое.
Красивый: сделать пропорциональное масштабирование + поворот для абсолютно интуитивности (-:
вот еще бы и примеры кода на каждый вариант, то было бы вообще хорошо
я, к сожалению, не умею на этом писать.

однако, думаю, имея формулы для коэффициента масштабирования и угла поворота вам не составит труда написать код.

или, лучше так: там есть affineTransform который поймёт целиком матрицу аффинного преобразования? Так можно двух зайцев сразу - и масштабирование и перемещение, и поворот. псевдокод я сейчас напишу.
CGAffineTransformMake
Returns an affine transformation matrix constructed from values you provide.

CGAffineTransform CGAffineTransformMake (
CGFloat a,
CGFloat b,
CGFloat c,
CGFloat d,
CGFloat tx,
CGFloat ty
);
Parameters
a
The value at position [1,1] in the matrix.

b
The value at position [1,2] in the matrix.

c
The value at position [2,1] in the matrix.

d
The value at position [2,2] in the matrix.

tx
The value at position [3,1] in the matrix.

ty
The value at position [3,2] in the matrix.

Return Value
A new affine transform matrix constructed from the values you specify.

документация говорит что матрица афинного преобразования подойдет как раз
Что-то математики получилось больше чем программирования. Кодом не отделаюсь, придется объяснять.

ну поехали: исходим из предположения что делается пропорциональное масштабирование с коэффициентом k и поворот на угол a.

коэффициенты поворота и масштабирования определяются так:
a = k cos(a)
b = k sin(a)
c = -k sin(a) = -b # вообще в общем случае k для x и y разный, но раз у нас масштабирование пропорциональное, получилось вот такое красивое "-b"
d = k cos(a) = a

сам по себе угол нас в рассчетах не волнует, я это расписал только чтобы показать что c и d зависят от a и b.

tx и ty - это вектор переноса начала координат, как я помню.

для начала посчитаем a и b. для удобства принимаем одну из точек касания за начало координат. тогда переноса не будет (tx и ty = 0)

относительные координаты второй точки (стартовые и текущие):

dstartx = startx1 - startx2
dstarty = starty1 - starty2

dlocx = locx1 - locx2
dlocy = locy1 - locy2

итого мы имеем такое вот преобразование:

| a b 0||dstartx| |dlocx|
|-b a 0||dstarty| = |dlocy|
| 0 0 1|| 1 | | 1 |


выписываем уравнения, решаем относительно a и b и получаем такие результаты:

b = (dlocx * dstarty - dstartx * dlocy) / (dstartx^2 + dstarty^2)
a = (dlocx * dstartx + dlocy * dstarty) / (dstartx^2 + dstarty^2)

осталось вычислить tx и ty. для этого вернемся обратно к изначальной системе координат и рассмотрим перенос первой точки (которую мы выше принимали за начало):


| a b tx| |startx1| |locx1|
|-b a ty| |starty1| = |locy1|
| 0 0 1| | 1 | | 1 |


расписываем в систему уравнений, получаем вектор переноса:
tx = locx1 - a * startx1 - b * starty1
ty = locy1 + b * startx1 - a * starty1

ну вот, имеем все данные для масштабирования, поворота и переноса:

b = (dlocx * dstarty - dstartx * dlocy) / (dstartx^2 + dstarty^2)
a = (dlocx * dstartx + dlocy * dstarty) / (dstartx^2 + dstarty^2)
c = - b
d = a

tx = locx1 - a * startx1 - b * starty1
ty = locy1 + b * startx1 - a * starty1

я, естественно, не гарантирую что это заработает: я мог ошибиться в нумерации строк-столбцов в матрице (черт их знает что они имели ввиду под [1,2] - первый столбец и вторую строку или первую строку и второй столбец), мог напутать знаки при a и b, ввиду того сто программистская система координат имеет нестандартную по математическим меркам ориентацию оси y, но в целом теория, как мне кажется, должна быть верна.

Это был вариант в котором изображение "прилипает" к точкам касания. Как мне кажется данное условие - обязательное для интуитивности мультитач-интерфейса. Как несложно заметить, чтобы найти все коэффициенты, мы вынуждены были сделать предположение о двух переменных (kx = ky = k). Несложно догадаться, что если ввести третью точку касания и "прилепить" изображение ещё и к ней, то можно посчитать матрицу аффинного преобразование в общем виде - с непропорциональным масштабированием.

Математический аппарат там похожий, разве что немного с другой стороны придется зайти (так легко подмена системы координат не проканает).

Удачи (-:

Если это заработает - пожалуйста, дайте знать.
черт, форматирвоание матриц разъехалось. ну да ладно, должно быть более-менее понятно.
ну конечно. налажал в относительных координатах. правильно будет так:

dstartx = startx2 - startx1
dstarty = starty2 - starty1

dlocx = locx2 - locx1
dlocy = locy2 - locy1

иначе у нас всё совсем не туда двигаться будет (-:
вобщем dstartx, dstarty, dlocx,dlocy я брал по модуляю

Изменение размера получилось хорошо, но поворот почему-то нормально работает только в 0-90 градусов.
И да, система координат в UIView такая: центр - в левом верхнем улгу. Вправо пошла ось X, вниз - ось Y
видимо именно потому что по модулю брал и не получается поворот. попробуй сделать startx2 - startx1, как я написал выше - должны работать повороты на все 360...
надо уезжать, поэтому сразу напишу как посчитать для трёх касаний.

имеем матрицу и три пары векторов в гомогенных координатах:

A =
|a b tx|
|c d ty|
|0 0 1|

start1 = (x1, y1, 1); start2 = (x2, y2, 1); start3 = (x3, y3, 1);
loc1 = (x1', y1', 1); loc2 = (x2', y2', 1); loc3 = (x3', y3', 1);

известно что:
|A||start1| = |loc1|
|A||start2| = |loc2|
|A||start3| = |loc3|

получаются нехитрые уравнения, которые надо решить относительно a, b, c, d, tx и ty (сразу перегруппирую чтобы удобнее было решать):

a x1 + b y1 + tx = x1'
a x2 + b y2 + tx = x2'
a x3 + b y3 + tx = x3'

c x1 + d y1 + ty = y1'
c x2 + d y2 + ty = y2'
c x3 + d y3 + ty = y3'

если из первого и второго вычасть третье, появляется лйгкий путь вычислить a и b:

a (x1 - x3) + b (y1 - y3) = x1' - x3';
a (x2 - x3) + b (y2 - y3) = x2' - x3';

(этот шаг эквивалентен трюку с переносом начала координат в одну из точек касания, который проделан камментом выше).

аналогично делается для второй тройки уравнений для c и d:

c (x1 - x3) + d (y1 - y3) = y1' - y3';
c (x2 - x3) + d (y2 - y3) = y2' - y3';

в общем виде вычисляются коэффициенты. потом подставляются в оставшиеся третье и шестое уравнения и получаются tx и ty.

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

Enjoy!
ааа! совсем забыл добавить. в случае с тремя точками нельзя допускать чтобы они лежали на одной прямой. Если конкретнее, то разумные коэффииенты и точность вычислений будет при некоей разумной ненулевой площади треугольника с вершинами в точках касания.

Площадь треугольника по координатам вычисляется по восьмой формуле из википедии

Не забываем взять результат по модулю.

Думаю при уменьшении площади меньше какой-то величины просто прекращать какие-либо преобразования и ждать пока она не увеличится снова. Если пальцы изначально на одной прямой стоят, то ждать пока площадь не увеличится и толко после этого запоминать стартовые координаты.
а, ну да. одновременно с масштабированием надо и перетаскивать, чтобы под пальцем при масштабировании всегда была одна и та же точка изначальной картинки. С "простым" методом выше работать не будет. с вашим и остальными двумя моими - будет.
К сожалению плюсануть еще не могу, поэтому скажу так. Огромное спасибо!!!
С удовольствие читаю Ваши статьи. И, если это возможно, продолжайте в том же духе!
У меня к сожалению в beta7 уже не компилируется :(

Немного поменялся синтаксис:
contentView переименовался в viewController;
MyView называется теперь HelloHabrViewController

соответственно self.contentView теперь тоже стал self.viewController (по моим догадкам)

Однако все равно не компилируется, ругается на:
[habrView setCenter:[self center]];
error: incompatible type for argument 1 of 'setCenter:'
А также появилось 4 ворнинга:
warning: 'UIViewController' may not respond to '-initWithFrame:'
warning: 'HelloHabrViewController' may not respond to '-setBackgroundColor:'
warning: 'HelloHabrViewController' may not respond to '-center'
warning: 'HelloHabrViewController' may not respond to '-addSubview:'
ну вообще-то MyView это наследник класса UIView, а если уж на то пошло, то HelloHabrViewController это наследник класса UIViewController.

Короче говоря, сейчас докачаю beta 7 и поправлю как надо и кину вам ссылку на новый вариант
блин, скачал beta 7, а архив битый оказался. Буду качать заново
что же за безобразие такое, только сдал сессию и скачал нормально beta 7, как они beta 8 выпустили. Теперь прийдется качать снова. Извине что так долго не отвечал. Если будут какие-то вопросы - пишите в личку
В симуляторе это тестировать невозможно, так?
Для тестирования нужны сертификаты от Apple (если писать в XCode и тестировать на девайсе)?
В симуляторе это тестировать невозможно, так?

кто сказал? в симуляторе тестируй сколько влезет
Для тестирования нужны сертификаты от Apple (если писать в XCode и тестировать на девайсе)?

да
Ой, я про второе нажатие в симуляторе :) Swipe/pinch никак не протестировать...
У тебя сертификат есть или существуют другие способы проверить на самом девайсе?
ну и что не так со вторым нажатием? Я же написал как это эмулировать
сертификата нет. Можно поставить прошивку 2.0 и вручную по ssh закидывать приложения, но эффект от этих действий сомнителен
Скажите, а этот рецепт на 8-й бете работает? телефона сейчас нету, проверить могу лишь на симуляторе. запускаю в дебаг-режиме свое приложение, посылающее по http-протоколу запросы каждые 5 секунд, затем нажимаю на home. несколько секунд (4-5) запросы еще идут, затем все прекращается. мне вот интересно - это у меня руки из пятой точки растут или же это баг симулятора? буду очень признателен за любую инфу по данному вопросу, т.к. возможность работы приложения в бэкграунде очень важна
по логике вещей, этот рецепт не должен работать ни в одной бете.

Какие есть объяснения:
- Home Screen уже показался, то applicationDidTerminate: еще не законцило работать
- возможно http запросы заносятся в какую-то глюбоальную очередь, и посылаются по мере ее освобождения
- глючит симулятор
Дело в том, что даже пример из данной статьи ведет себя аналогичным образом. я прицепил таймер, который каждую секунду смещает картинку на 1 пиксель вправо и вниз. если нажать хоум и подождать около пяти секунд - картинка вернется на исходную позицию. если подождать меньше и запустить приложение - картинка будет продолжать смещаться... эх, мне бы айфон для тестовых целей =))
Sign up to leave a comment.

Articles