усложним немного наше приложение, которое отображало логотип хабра.
Я буду использовать iPhone SDK beta 4, проект от beta 2 подошел и откомпилировался. Если будут проблемы с компиляцией проекта — пишите в каментах.
Приступим. Сделаем так, чтобы при одном касании и ведении пальца логотип хабра двигался за пальцем, а при касаниях двумя пальцами и изменениями их положений логотип масштабировался.
Для начала подключим к файлу MyView.m заголовочный файл math.h. Далее в конструкторе класса MyView — -(id)initWithFrame:(CGRect)frame в блоке if допишем две строки:
как видно, мы явно указываем, что хотим чтобы наш UIView и UIImageView, в котором находится логотип хабра поддерживали несколько касаний.
Теперь относительно обработки касаний. В классе UIView определены следующие обработчики касаний:
— (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesChangedWithEvent:(UIEvent *)event;
— (void)touchesCancelled;
исходя из их названий не сложно догадаться в каком случае какой использовать
Определим две глобальные переменные(в заголовочный файл их заносить не надо): CGPoint startLoc0,startLoc1. В них будем хранить точки начальных касаний, если касаний два.
Теперь определим функцию обработки начала касания:
Теперь определим функцию изменения положения касаний:
В случае с одним касанием, просто переносим картинку в точку касания. В случае с двумя касаниями я вычисляю коэфициент растяжения. Я выбрал свой метод вычисления коэфициентов, если у вас есть другие идеи по поводу вычисления, то пишите в каментах.
Чтобы отмасштабировать изображение, я воспользовался функцией setTransform:, которая в качестве параметра получает матрицу афинного преобразования. Стоит заметить, что при исользовании функции CGAffineTransformMakeScale конечная картинка будет растянута по коэфициентам исходя из своего начального размера, а не текущего.
Но теперь остался основной вопрос: а как симулировать на эмуляторе несколько одновременных касаний? В результате загугливания выяснилось, что достаточно зажать кнопку Option.
Запускаем и радуемся результату:

Добавим еще одну мелочь под названием splash screen. Splash screen — это картинка, которая будет отображаться сразу после клика по значку программы и до окончания работы функции — (void)applicationDidFinishLaunching:(UIApplication *)application. Полезно если хотите вывести краткую информацию про программу, производителя, версию и т.д.
Чтобы добавить splash screen к программе достаточно добавить в проект png файл с названием Default.png. Естесственно лучше чтобы этак картинка было с разрешением таким же как и экран iPhone.
как всем известно, с помощью SDK нельзя создавать приложения, работающие в фоне. Но это не означает, что при нажатии на кнопку Home ваше приложение закроется. Можно переопределить некоторые функции в классе UIApplication и указать программе, что необходимо использовать переопереденный класс.
Создадим новый Objective-C класс, назовем его ApplicationSuspend, этот класс будет наследником класса UIApplication.
Содержание h файла должно быть таким:
Содержание m файла должно быть таким:
Как видим, просто определили функцию applicationSuspend. Этого достаточно, чтобы при нажатии на кнопку Home программа уходила в suspend, а при нажатии на иконку — возвращалась.
Также можно переодпределить функции applicationResume:, menuButtonUp:, menuButtonDown:, launchApplicationWithIdentifier:suspended:.
Описание того, что так можно сделать, в офф документации не нашел, но нашел здесь. Но пока в iPhone SDK красуется надпись beta, то это можно простить.
А теперь самое главное, как указать программе, что следует использовать измененный UIApplication?
Откройте файл main.m и найдите строку:
    int retVal = UIApplicationMain(argc, argv, nil, @«HelloHabrAppDelegate»);
как видим, третий парамет задан nil, вот как раз вместо него и надо вписать название измененного нами класса:
    int retVal = UIApplicationMain(argc, argv, @«ApplicationSuspend», @«HelloHabrAppDelegate»);
Если все делали правильно, то запустите программу, переместите логотип хабра, нажмите на Home и потом снова войдите в программу, логотип должен остаться на прежнем месте.
Файл проекта здесь
Я буду использовать iPhone SDK beta 4, проект от beta 2 подошел и откомпилировался. Если будут проблемы с компиляцией проекта — пишите в каментах.
multitouch
Приступим. Сделаем так, чтобы при одном касании и ведении пальца логотип хабра двигался за пальцем, а при касаниях двумя пальцами и изменениями их положений логотип масштабировался.
Для начала подключим к файлу MyView.m заголовочный файл math.h. Далее в конструкторе класса MyView — -(id)initWithFrame:(CGRect)frame в блоке if допишем две строки:
[self setMultipleTouchEnabled:YES];
[habrView setMultipleTouchEnabled:YES];
как видно, мы явно указываем, что хотим чтобы наш UIView и UIImageView, в котором находится логотип хабра поддерживали несколько касаний.
Теперь относительно обработки касаний. В классе UIView определены следующие обработчики касаний:
— (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
— (void)touchesChangedWithEvent:(UIEvent *)event;
— (void)touchesCancelled;
исходя из их названий не сложно догадаться в каком случае какой использовать
Определим две глобальные переменные(в заголовочный файл их заносить не надо): CGPoint startLoc0,startLoc1. В них будем хранить точки начальных касаний, если касаний два.
Теперь определим функцию обработки начала касания:
— (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  if ([touches count] == 2) {
    startLoc0 = [[[touches allObjects] objectAtIndex:0] locationInView:self];
    startLoc1 = [[[touches allObjects] objectAtIndex:1] locationInView:self];
    if (startLoc0.x == startLoc1.x) startLoc0.x+=0.05;
    if (startLoc0.y == startLoc1.y) startLoc0.y+=0.05;
  }
}
Теперь определим функцию изменения положения касаний:
— (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  if([touches count] == 1) {
    UITouch *touch = [touches anyObject];
    if ([touch view] == habrView) {
      CGPoint location = [touch locationInView:self];
      [habrView setCenter:location];
    }
  }
  else if ([touches count] == 2) {
    UITouch *touch0 = [[touches allObjects] objectAtIndex:0];
    UITouch *touch1 = [[touches allObjects] objectAtIndex:1];
    CGPoint loc0 = [touch0 locationInView:self];
    CGPoint loc1 = [touch1 locationInView:self];
    CGFloat scaleX = fabs((loc0.x — loc1.x)/(startLoc0.x — startLoc1.x));
    CGFloat scaleY = fabs((loc0.y — loc1.y)/(startLoc0.y — startLoc1.y));
    [habrView setTransform:CGAffineTransformMakeScale(scaleX, scaleY)];
    }
  else
    NSLog(@«too many touches :(»);
}
В случае с одним касанием, просто переносим картинку в точку касания. В случае с двумя касаниями я вычисляю коэфициент растяжения. Я выбрал свой метод вычисления коэфициентов, если у вас есть другие идеи по поводу вычисления, то пишите в каментах.
Чтобы отмасштабировать изображение, я воспользовался функцией setTransform:, которая в качестве параметра получает матрицу афинного преобразования. Стоит заметить, что при исользовании функции CGAffineTransformMakeScale конечная картинка будет растянута по коэфициентам исходя из своего начального размера, а не текущего.
Но теперь остался основной вопрос: а как симулировать на эмуляторе несколько одновременных касаний? В результате загугливания выяснилось, что достаточно зажать кнопку Option.
Запускаем и радуемся результату:

splash screen
Добавим еще одну мелочь под названием splash screen. Splash screen — это картинка, которая будет отображаться сразу после клика по значку программы и до окончания работы функции — (void)applicationDidFinishLaunching:(UIApplication *)application. Полезно если хотите вывести краткую информацию про программу, производителя, версию и т.д.
Чтобы добавить splash screen к программе достаточно добавить в проект png файл с названием Default.png. Естесственно лучше чтобы этак картинка было с разрешением таким же как и экран iPhone.
application suspend
как всем известно, с помощью SDK нельзя создавать приложения, работающие в фоне. Но это не означает, что при нажатии на кнопку Home ваше приложение закроется. Можно переопределить некоторые функции в классе UIApplication и указать программе, что необходимо использовать переопереденный класс.
Создадим новый Objective-C класс, назовем его ApplicationSuspend, этот класс будет наследником класса UIApplication.
Содержание h файла должно быть таким:
#import <UIKit/UIKit.h>
interface ApplicationSuspend: UIApplication {
}
end
Содержание m файла должно быть таким:
#import «ApplicationSuspend.h»
@implementation ApplicationSuspend
— (void) applicationSuspend:(struct __GSEvent*) event {
}
end
Как видим, просто определили функцию applicationSuspend. Этого достаточно, чтобы при нажатии на кнопку Home программа уходила в suspend, а при нажатии на иконку — возвращалась.
Также можно переодпределить функции applicationResume:, menuButtonUp:, menuButtonDown:, launchApplicationWithIdentifier:suspended:.
Описание того, что так можно сделать, в офф документации не нашел, но нашел здесь. Но пока в iPhone SDK красуется надпись beta, то это можно простить.
А теперь самое главное, как указать программе, что следует использовать измененный UIApplication?
Откройте файл main.m и найдите строку:
    int retVal = UIApplicationMain(argc, argv, nil, @«HelloHabrAppDelegate»);
как видим, третий парамет задан nil, вот как раз вместо него и надо вписать название измененного нами класса:
    int retVal = UIApplicationMain(argc, argv, @«ApplicationSuspend», @«HelloHabrAppDelegate»);
Если все делали правильно, то запустите программу, переместите логотип хабра, нажмите на Home и потом снова войдите в программу, логотип должен остаться на прежнем месте.
Файл проекта здесь