среда, 8 января 2014 г.

Эффект листания изображения для Iphone, IOS 5+

В этой статье я расскажу как сделать эффект листания изображений как страниц в книге или в отрывном календаре. Очень часто приходится сталкиваться с задачами реализовать мини галерею или список изображений. Что бы сделать интерфейс красивым и понятным для пользователя есть множество путей. Сегодня я покажу как быстро и просто сделать листание изображений, что бы они переворачивались как листы при помощи протягивания пальцем по экрану, Этот принцип конечно же построен на работе с GestureRecognizer.

Для начала создайте проект в Xcode выбрав Single View Application. (Я работаю в Xcode 4.6 поэтому буду показывать на примере с использованием Storyboard)
Название не имеет значения. Ставим галочку Use Storyboards и сохраняем проект где нибудь себе в папку. Так у нас создастся наш коренвой ViewController  с именем которое вы указали в качестве названия приложения и наш  Storyboard.


Давайте сразу приступим к созданию UIimageView который будет перелистыватся. Перейдите на ваш Storyboard он пока пустой и добавим мы в него пока всего одну картинку при помощи  элемента  UIimageView Найдите его в списке объектов и разместите на вашей Storyboard.

Теперь в h файле вашего контроллера необходимо создать IBOutlet для связи с нашим UIImageView
Вот как это выглядит у меня:
@interface testViewController : UIViewController{
IBOutlet UIImageView *myimage;
}
Теперь можно назначить New Referensing Outlet Collections нашему myimage.

 Затем выбираем New Referensing Outlet Collections нажимая левой кнопкой мышки на кружочке и тянем к левому блоку в наш UIView. И связываем с myimage.

Теперь UIImageView можно назначить картинку и сделать это можно через опять таки Storyboard, как это показано на рисунке.
Также очень важно не забыть поставить галочку Use Interaction Enabled

Далее переходим к m файлу нашего контроллера и находим в нем метод – (void)viewDidLoad
Добавим туда  код который по сути привяжет использования жеста Swipeк нашей картинке и заставит её переворачиваться в зависимости от горизонтальных движений пальцами по экрану телефона.
 [myimage setUserInteractionEnabled:YES];
//перетащили пальцем вправо
UISwipeGestureRecognizer *swipenext = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(getNext)];
[swipenext setDirection:UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionLeft];
[myimage addGestureRecognizer:swipenext];
//перетащили пальцем влево
UISwipeGestureRecognizer *swipeback = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(getPrev)];
[swipeback setDirection:UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionRight];
[myimage addGestureRecognizer:swipeback];
Теперь подробней поговорим о коде.
UISwipeGestureRecognizer *swipenext = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(null)]; – создаёт объект жеста swipenext с параметрами
Обратите внимание на параметр action:@selector(getNext) – сдесь мы можем указать метод который выполнится после перелистывания например это может быть показать следующую картинку getNext.  Посмотрим реализацию этого метода
-(void) getNext{
//устанавливаем анимацию переворачивания
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1]; // сколько длится анимация – в секундах
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:myimage cache:YES]; //овернуть «листок» вверх
[UIView commitAnimations];
}
// почти тоже самое в метотоде getPrev
-(void) getPrev{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:myimage cache:YES]; //отвернуть листок вниз
[UIView commitAnimations];
}
Теперь запустим проект и потягаем мышкой по экрану эмулятора (или телефона если вы работаете с реальным девайсом). вы должны увидеть перелистывание подобное этому:

Конечно в качестве направления переворачивания листа в параметр setAnimationTransition  можноустанавливать значения UIViewAnimationTransitionFlipFromLeft и UIViewAnimationTransitionFlipFromRight но это уже будет просто поворот рисунка, а не перелистывание.
Пока конечно же рисунок остаётся тем же, что и был но мы можем вставить метод который менял бы что то например между строк
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:myimage cache:YES];
//добавить сюда выполнение метода
[UIView commitAnimations];
Тогда сможем реализовать подмену рисунка плавно, а пока на этом всё спасибо. что прочиталю статью.

Работа с фото видео камерой в IOS IPhone используя UIImagePickerController

У многих разработчиков мобильных приложений возникает вопрос о реализации работы с камерой. Я уже описывал этот процесс для Android теперь хочу сделать краткое описание для IOS на IPhone. Речь пойдёт именно об использовании UIImagePickerController как самого простого способа. Описывать подробно создание проекта и установки кнопки в storyboard я не буду это вы можете посмотреть в моей прошлой статье.

Предпочитается, что у вас уже есть кнопка по которой мы хотим вызвать камеру и получить например фото после того как вы нажмете фотографировать. Поэтому я опишу лишь методы которые необходимо реализовать в класе вашего ViewCotroller-а.
Итак вызов камеры:
-(IBAction) makePhoto:(id)sender{
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]){
// Создание image picker controller
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// Устанавливаем сорс для камеры
imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;
imagePicker.videoQuality = UIImagePickerControllerQualityTypeHigh;
// Текущий Delegate
imagePicker.delegate = self;
imagePicker.mediaTypes = [UIImagePickerController  availableMediaTypesForSourceType:imagePicker.sourceType];
// Показываем image picker
[self presentModalViewController:imagePicker animated:YES];
}else{
NSLog(@»Ваше устройство не поддерживает эту функцию»);
}
}
В этом методе мы настраиваем UIImagePickerController и показываем пользователю активность в которой он работает, и соответственно можно сделать фото. Поскольку делегатом является self,  то есть реализация методов обработки полученных результатов должна быть в этом же классе.
Подвяжите метод типа IBAction к кнопке на Tuch up inside и запустите проект. Конечноже проверять необходимо на реальном устройстве, так как на эмуляторе камеры нет и в системный лог вы получите сообщение «Ваше устройство не поддерживает эту функцию». так как в строке
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]){
мы проверяем наличие камеры на устройстве. Итак если вы запустите проект на реальном устроействе и нажмете на свою кнопку то увидите, что запустилась активность камеры, теперь можно сделать фото. Но после нажатия кнопки Use ничего не произойдет так как нам нужно реализовать ещё метод - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info поскльку делегатом для UIImagePickerController является данный класс в котором он вызван,
Итак код метода:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//определить медиа тип файла
NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ( [ mediaType isEqualToString:@"public.image" ]) { //если файл – изображение
// Берем изображение из информации словаря
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
//получить путь к файлу
NSURL* imagePath = (NSURL *)[info valueForKey:UIImagePickerControllerReferenceURL];
NSString* chosed_imagePath = [imagePath path];
//формируем file-data изображения
NSData* imageData = UIImageJPEGRepresentation(image, 1.0);
}else if ( [ mediaType isEqualToString:@"public.movie" ]){ // пользователь снял видео
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
}
}
Теперь подробнее. Как видно из данного примера мы можем получить 2 типа контента с камеры: фото и видео. У данных о фотографии мы можем получить путь, url и NSData то есть само байтовое представление файла, и  что немало важно NSData хранится в памяти и если вам не нужны эти данные лучше не хнатить их в ОЗУ а пользоваться файлом на мобильном устройстве . Поэтому как дальше работать с этими данными вам решать) У видео файла также можно получить путь и NSData но в отличии от фото оно уже в медиа-галерее вашего устройства. И так опишу ещъ один метод для сохранения изображения в медиа галерею для дальнейшей работы с ним.
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
Как вы видите в качетсве входного параметра в этом методе используется image объект типа UIImage полученный нами из камеры. Еесли вам это нужно используйте это вот так:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//определить медиа тип файла
NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ( [ mediaType isEqualToString:@"public.image" ]) { //если файл – изображение
// Берем изображение из информации словаря
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}else if ( [ mediaType isEqualToString:@"public.movie" ]){ // пользователь снял видео
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
}
}
Конечно возможно вам понадобится обработчик didFinishSavingWithError – это метод который выполнится после сохранения рисунка и может содержать ошибку, о которой нужно сообщить пользователю
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
// проверка на ошибки
if (error != NULL) {
// показать ошибку…
UIAlertView* minhaCritica = [UIAlertView new];
minhaCritica.title = @»Ошибка»;
[minhaCritica addButtonWithTitle:@"Ок"];
minhaCritica.message = @»Фото не сохранилось»;
minhaCritica.delegate = self;
[minhaCritica show];
[minhaCritica release];
//это обычный алерт с кнопкной ОК и сообщением
} else  // ошибок нет
{
// показать сообщение о том что картинка сохранена
UIAlertView* minhaCritica = [UIAlertView new];
minhaCritica.title = @»Успешно»;
[minhaCritica addButtonWithTitle:@"Ок"];
minhaCritica.message = @»Фото  сохранилось»;
minhaCritica.delegate = self;
[minhaCritica show];
[minhaCritica release];
}
}
Как мы видим в обработчике идет проверка на ошибку и два варианта или успешно или неудачно тогда покажем alert с тем или иным тектом. Теперь можно запустить проект и проверить как работает получение фото с камеры и сохраненеи в галерею.

Правильный разоворот изображения в IOS

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

И так приступим. Подразумевается что у вас уже есть проект с размещенным на ViewVontroller-е вашей UIImageView куда вы будете показывать картинку до и полсе разворота. Поэтому я опишу лишь методы по работе с самим изображением.
Итак в методе viewDidLoad я подгружаю картинку из проекта
UIImage *img = [UIImage imageNamed:@"test.png"];
mainimage.image = img;
где mainimage это ваш UIImageView
Теперь релазуем два метода для переворота картинки вправо и влево:
-(void) RotateToLeft{
mainimage.image = [self imageByRotatingImage:img fromImageOrientation:UIImageOrientationLeft];
}
-(void)RotateToRight{
mainimage.image = [self imageByRotatingImage:img fromImageOrientation:UIImageOrientationRight];
}
Конечно вы можете написать эти методы как -(IBAction) и привязать вызов к кнопкам, но это не слишком сложно, что бы тратить на это время в этой статье :)
Итак мы видим, что в обоих случаях вызывается один и тот же метод -(UIImage*)imageByRotatingImage:(UIImage*)initImage fromImageOrientation:(UIImageOrientation)orientation только с разным параметром вконце. Он то как раз и указывает на ориентацию изображения в которую необходимо повернуть  картинку. Взял я его гдето на просторах интернетов и немножко окрасивил для понятного использования. Перед просмотром листинга кода метода хочу сказать, что перед его вызовом подразумевается, что текущая картинка имеет ориентацию UIImageOrientationUp.
Итак сам метод:
-(UIImage*)imageByRotatingImage:(UIImage*)initImage fromImageOrientation:(UIImageOrientation)orientation
{
CGImageRef imgRef = initImage.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = orientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
return initImage; //если прислать в качестве параметра orientation – UIImageOrientationUp метод вернёт саму картинку целой и невредмой
break;
case UIImageOrientationUpMirrored: //EXIF = 2  – Зеркальное отображение
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3 – перевернет вертикально
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4 – Вертикальное зеркальное отображение
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6 – Перевернуть влево -90 градусов
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8 – Вправо тоесть +90 градусов по часовой стрелке
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
// Вот тут создается графический контекст
CGContextRef    context = NULL;
void *          bitmapData;
int             bitmapByteCount;
int             bitmapBytesPerRow;
bitmapBytesPerRow   = (bounds.size.width * 4);
bitmapByteCount     = (bitmapBytesPerRow * bounds.size.height);
bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL)
{
return nil;
}
CGColorSpaceRef colorspace = CGImageGetColorSpace(imgRef);
context = CGBitmapContextCreate (bitmapData,bounds.size.width,bounds.size.height,8,bitmapBytesPerRow,
colorspace,kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorspace);
if (context == NULL)
// если неполучилось создать контекст по какой либо причине отдатим nil
return nil;
CGContextScaleCTM(context, -1.0, -1.0);
CGContextTranslateCTM(context, -bounds.size.width, -bounds.size.height);
CGContextConcatCTM(context, transform);
//Отрисовка изображения в графический контекст в памяти
CGContextDrawImage(context, CGRectMake(0,0,width, height), imgRef);
CGImageRef imgRef2 = CGBitmapContextCreateImage(context);
CGContextRelease(context);
free(bitmapData);
UIImage * image = [UIImage imageWithCGImage:imgRef2 scale:initImage.scale orientation:UIImageOrientationUp];
NSData *newimageData = UIImageJPEGRepresentation(image,1.0);
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:newimageData  forKey:@"chosed_image_data"];
CGImageRelease(imgRef2);
return image;
}
Во время выполнения этого метода может быть некая задержка в приложении, так как идёт выделение памяти и устройство в отличии от эмулятора может слегка притормозить свою активность, поэтому нужно быть готовым к этому. Итак мы имеем универсальный метод по развороту картинки на 90 и 180  градусов в любую сторону, а также возможность зеркально отобразить изображения. При этом сохраняя его в контексте. Чем это лучше чем просто трансформация в виде анимации? Потому, что после например анимированного траснформа поворота мы получим картинку повернутую на 90 градусов, но в контексте она останется в прежнем состоянии. И при повторном выполнении трансформации мы получим тот же результат – картинку развернутую на 90 градусов, а не на 180 как задумывалось.

Пропорциональное изменение размеров изображений в IOS IPhone

Статья посвящена теме об пропорциональном изменении размеров фотографий в вашем приложении для IPone IPad. Так как в большинстве приложений по работе  с фотографиями рано или поздно разработчик сталкивается с задачей уменьшить или увеличить размер фото согласно заданным величинам ширины или величины. И уменьшение необходимо сделать пропорционально например ширине как это зачастую бывает. Так как если просто накинуть пару сотен пикселов ширине или высоте картинки полученное изображение может иметь искажённый вид, например растянуто по высоте. Это может и сойдет если работа идет с объектами типа дерево или куст, но никак не удовлетворит заказчика если вы работаете с фотографиями людей. А также возможно вам просто необходимо уменьшить размеры фото что бы не тратить драгоценный мобильный трафик при передаче фотографии друзьям.

Итак сама реализация:
Как обычно предполагаю что у вас уже есть проект с созданным в storyboard UIImageView для работы с изображениями. viewDidLoad я подгружаю картинку из проекта
UIImage *img = [UIImage imageNamed:@"test.png"];
mainimage.image = img;
где mainimage это ваш UIImageView
Теперь напишем метод в который можно привязать к кнопке, по нажатию на котороую мы уменьшаем реальный размер фото пропорционально по ширине до 640px.
-(IBAction) scale:(id)sender{
// создаем объект класса CGSize что бы задать пропорции нового фото
// первый параметр это ширина второй высота, но играет роль только размер для ширины так как метод ориентирован именно на пропорциональное уменьшение/увеличение по ширине
CGSize sz = CGSizeMake(640, 640);
UIImage *img = [UIImage imageNamed:@"test.png"];
UIImage *newimage = [self ScaleImgPropoWidth:img scaledToSize:sz];
mainimage.image = newimage;
}
Как вы видите реализация скрыта в методе ScaleImgPropoWidth, давайте посмотрим на реализацию метода:
- (UIImage *)ScaleImgPropoWidth:(UIImage *)image scaledToSize:(CGSize)newSize {
double ratio;
double delta;
CGPoint offset;
//проверка на то если новый размер картинки больше или равен старому то вернуть ту же картинку
if(newSize.width>=image.size.width){
return image;
}//если данная проверка вам ненужна вы можете её убрать, напрмиер если хотите в любом случае кропить размер или же при увеличении размеров заменить условие на if(newSize.width<=image.size.width)
ratio = newSize.width / image.size.width;
delta = (ratio*image.size.height – ratio*image.size.width);
UIImage *scaledImage =
[UIImage imageWithCGImage:[image CGImage]
scale:(image.scale / ratio)
orientation:(image.imageOrientation)];
CGRect clipRect = CGRectMake(0, 0,
scaledImage.size.width,
scaledImage.size.height);
CGSize sz = CGSizeMake(newSize.width, scaledImage.size.height);
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0);
} else {
UIGraphicsBeginImageContext(sz);
}
UIRectClip(clipRect);
[image drawInRect:clipRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Как вы могли заметить преобразовании резамера происходит в графическом контексте, то есть это не просто трансформация изображения.

UITableView в нутри UIViewContrloller. IOS программирование

В этой статье я опишу как сделать полноценную таблицу UITableView  в вашем UIViewController. Так как работать с UITableViewController несколько сложнее. Этот метод поможет вам сэкономить время. Пример будет показана на основе работы с Xcode 4.6 и использованием stroryboard. Удобство такого метода даёт возможность размещать на вашем UIViewController и другие элементы кроме таблици UITableView, такие как NavigationBar или UITabbar  и они будут нормально смотрется, а не ездить за последней строчкой таблици(вдруг кто сталкивался с проблемой).  Для начала вам необходимо создать проект, описывать эти простые действия я не буду так как в интернетах полно документации как это сделать. И так разместите на вашем UIViewController элемент UITableView как показано на рисунке:


Теперь создайте класс в своем приложении или используйте класс который создал за вас Xcode. Я назвал свой katalog. Привяжите его к вашему UIViewController если это все таки новый класс и новый UIViewController. Иначе если вы используете уже созданный то делать этого не придется.
Теперь необходимо немного модифицировать h файл:
вот мой katalog.h
#import
@interface katalog : UIViewController {
IBOutlet UITableView *table;
}

@end
Обратите внимание на это означает, что этот класс будет делегатом для таблици и источником данных.
IBOutlet UITableView *table; это аутлет для нашего UITableView его нужно подвязать к таблице нажатием правой кнопкой мыши на элементе UITableView и перетянув от New Referencing Outler  к вашему класу в левой колонке где показаны все Scene – активности вашего приложения.
Теперь приступим к реализации нашего m файла, в моём случае это katalog.m. В метод - (void)viewDidLoad я добавил 2 строки:
[table setDelegate: self];
[table setDataSource: self];
Указывая уже объекту table  кто будет делегатом и источником данных для него (по сути для таблици).
Поскольку наш класс является делегатом и источником данных для таблици необходимо реализовать стандартные методы для UITableView, изначально в m файле их нет поэтому придется добавить. В таблице будет две секции без названия и в каждой их них по одной строке с какими либо данными. Все это опишем в методах таблици.
Вот листинг кода который необходимо добавить в m файл:
#pragma mark – Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Количество секций в таблице.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Вернуть количество строк в секции.
return 1;
}
/*
Сформировать строки таблици
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *lang = [userDefaults objectForKey:@"lang"];
static NSString *CellIdentifier = @»Cell»;
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] ;
}
if(indexPath.row==0 && indexPath.section==0){
cell.text = @»Первая строка»;
//сформировать дату и перевести её в строку
//это просто пример какие данные можно добавить в таблицу
NSDate *d = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd_HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"..."]];
NSString *date = [formatter stringFromDate:d];
cell.detailTextLabel.text = date;
}else if(indexPath.section==1){
cell.text = @»Вторая строка»;
cell.detailTextLabel.text = @»ваши данные»;
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark – Table view delegate
/*
Обработка событий нажатия на строки таблици
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row==0 && indexPath.section==0){
//нажали на первую строку в первой секции
}else{
//нажали на другую строку
}
}

Конечно неплохо было бы изменить немножко внешний вид таблицы, для этого в настройках UITableView в storyboard и поставил опцию Grupped в параметре Style как показано на рисунке:

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

UITableView в нутри UIViewContrloller. Часть 2 – большие списки

В предыдущей части я описывал как создавать таблицы внутри UIViewContrloller, простейшим способом. Теперь поговорим о создании таблиц с большим количеством строк и сложными механизмами их формирования. Как создать проект и разместить UITableView описывать не буду можете посмотреть в предыдущей части. В данном примере мы будем выводить большое количество данных в качестве строк в таблицу. Для начала подправим наш h файл, если помните у меня это попрежнему katalog.h вот как он будет выглядеть:
#import
@interface katalog : UIViewController {
IBOutlet UITableView *table;
}
@property (strong,nonatomic)NSMutableArray* listOfItems;
-(void) prepereList;
@end

На самом деле я добавил только свойство listOfItems в качестве данных для него будет некий массив элементов в последствии строк. И добавил еще вспомогательный метод -(void) prepereList; – который будет готовить данные для выгрузки в таблицу, собственно наполнять listOfItems.
Релизация этого метода в m файле:
-(void) prepereList{
NSMutableArray *marray = //предположим что такой массив данных у вас есть, если нет то можете воспользоватся любыми примерами по формированию данных этого типа
//создадим объект типа массив для ключей уже существующих  значений из marray нашего массива данных строк
NSArray *keylist = [[NSArray alloc] initWithArray:marray];
//объявим наше свойство listOfItems.
listOfItems = [[NSMutableArray alloc] init];
NSDictionary *emDict = [NSDictionary dictionaryWithObject:keylist forKey:@"Sometext"]; //создадим ключ секцию и в качестве NSDictionary сохраним объект массив
//присвоим данные нашему списку элементов таблици
[listOfItems addObject:emDict];
}
Также не забудьте сделать @synthesize listOfItems;
Конечно кажется что метод несколько замутный и излишне орудует массивами. Дело в том что именно этот способ подходит мне для дальнейшей работы с данными, если захотите его упростить то можете это делать.
Далее незабываем включить наш метод в метод viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
[table setDelegate: self];
[table setDataSource: self];
[self prepereList];
}
Несколько изменятся методы по работе с таблицей относительно первой статье:
#pragma mark – Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [listOfItems count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *dictionary = [listOfItems objectAtIndex:section];
NSArray *array = [dictionary objectForKey:@"Sometext"];
NSLog(@»%d»,[array count]);
return [array count];
}
/*
Сформировать строки таблици
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @»Cell»;
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] ;
}
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSMutableArray *marray = [dictionary objectForKey:@"Sometext"];
NSDictionary *d = [marray objectAtIndex:indexPath.row];
NSString *code =  [d valueForKey:@"code"];
cell.text = @»Maintext»;
UIFont *myFont = [ UIFont fontWithName: @"System" size: 17.0 ];
cell.textLabel.font = myFont;
cell.tag = 1;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.detailTextLabel.text = @»datail»;
return cell;
}
#pragma mark – Table view delegate
/*
Обработка событий нажатия на строки таблици
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row==0 && indexPath.section==0){
//нажали на первую строку в первой секции
}else{
//нажали на другую строку
}
}
Немного не понятно откуда берутся данные, но сама реализация направлена на то, что бы показать как вывести большое количество строк автоматически, а не на то как сформировать данные для таблицы. Так что уж простите что не акцентирую внимание на этом.

Есть ещё один метод для формирования заголовков секций таблици, можете добавить его прямо в m  файд:
/**
заголовки секций
*/
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *sectioname = @»Заголовок»;
return sectioname;
}
Вызов этого метода генерирует сам TableView, и искать его он будет в нашем классе, так как именно наш класс katalog.m – делегат таблици. В качестве входного параметра section используется номер секции, в данном примере у меня одна секция и проверять это значения смысла нет. Поэтому я просто верну  название строкой. Можете скомпилировать проект и посмотреть как изменится вид таблици, над списокм появится заголовок.

Objective C регулярные выражения. NSRegularExpression поиск совпадений

Конечно же в разработке мобильных приложений под IPhone Ipad встречаются случаи когда необходимо использовать регулярные выражения. Сегодня я опишу метод и саму работу с регулярными выражениями для поиска совпадений в тексте. Для начала реализуйте метод описанный в листинге наже:
//в качестве входного параметра мы передаём в метод текст в котором необходимо найти совпадния
-(NSArray*) getMatchesfromstr:(NSString *)text{
/*пускай мы будем искать в тексте маркировку бензина А92 или А95 или А 80*/
NSRegularExpression *nameExpression = [NSRegularExpression regularExpressionWithPattern:@"(A ?[0-9]{2})» options:NSRegularExpressionSearch error:nil];
NSArray *matches = [nameExpression matchesInString:text
options:0
range:NSMakeRange(0, [text length])];
//на выходе получим массив найденных элементов
return matches;
}
Как видите метод не сложный для понимая основан на использовании NSRegularExpression, Далее посмотрим сам вызов и использование метода.

Итак добавим следующий код в нужный вам метод:
NSString *text = @»Текст для проверки и поиска бензана A92 или же с пробелом А 80.»;
//собственно вызов метода
NSArray *matches = [self getMatchesfromstr:text];
// проверяем найдено ли что либо
if([matches count]>0){
//далее цикл перебора элементов
for (NSTextCheckingResult *match in matches) {
NSRange matchRange = [match rangeAtIndex:0];
NSString *matchString = [text substringWithRange:matchRange];
NSLog(@»%@»,matchString);
}
}
Вот собственно и все, мы нашли совпадения и вывели их в лог. Дальше как с ними работать вам решать.

Полезные методы и функции для IOS разработчиков

В этой статье я кратко, но с пояснениями опишу несколько небольших, но очень полезных методов решения некоторых проблем при разработке под IPhone/IPad. Для многих опытных программистов эти методы возможно и не секрет, но для новичков жадно рыщущих по просторам интернет в поисках хоть какой либо русскоязычной информации будет полезно. Например как показать окно выбора фото из галереии телефона или IPad-а, или же сделать тень какому либо элементу.
Итак начнем с небольшого метода который позволит создать папку в директории Documents вашего устройства с использованием NSFileManager.
-(void) CreatefolderpathinEdirectory:(NSString *)folder{
NSArray *dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPath objectAtIndex:0];
NSString *path = [docsDir stringByAppendingPathComponent:folder];
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:nil];
}
В качестве входного параметра я передаю имя директории. Метод проверяет существует ли папка, если нет то создаст её.
Далее рассмотрим метод который позволит открыть фото галерею вашего устройства и выбрать из него фото:
-(void) openGallery{
//создаём объект пикер контроллера
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
//задаём опции
picker.videoQuality = UIImagePickerControllerQualityTypeHigh;
picker.delegate = self;
picker.allowsEditing = NO;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.mediaTypes = [UIImagePickerController  availableMediaTypesForSourceType:picker.sourceType];
//проверим на каком устройстве выполняем операцию
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { //Если запустили на устройстве ipad
//создаём всплывающее онкно для выбора файла
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:picker];
//опции всплывающего окна
[self.popoverController presentPopoverFromRect:CGRectMake(220.0, 680.0, 330.0, 400.0)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown  animated:YES];
} else {//запустили на  iphone
//покажем модальное оконо пикера
[self presentModalViewController:picker animated:YES];
}
}
Если вы заметили функционал для IPad несколько отличается, так как по сути модальное окно вызвать нельзя мы вызовем всплывающее окошко с заданными координатами от которых оно будет строится и стрелкой указывающей например на кнопку которая вызвала действия.
Далее рассмотрим обработчик результата после выбора фото или видео файла:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//определить медиа тип файла
NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ( [ mediaType isEqualToString:@"public.image" ]) { //если файл – изображение
// Берем изображение из информации словаря
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
//получить путь к файлу
NSURL* imagePath = (NSURL *)[info valueForKey:UIImagePickerControllerReferenceURL];
NSString* chosed_imagePath = [imagePath path];
//формируем file-data изображения
NSData* imageData = UIImageJPEGRepresentation(image, 1.0);
//Это собственно стандартный набор данных о фото которые можем вытянуть
}else if ( [ mediaType isEqualToString:@"public.movie" ]){ //если файл видео
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path]; // путь к ролику на устройстве
}
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {//ipad
//закрыть всплывающее окно
[self.popoverController dismissPopoverAnimated:YES];
}else{ // iphone
//закрыть модальное окно пикера
[self dismissModalViewControllerAnimated:YES];
}
}
Углублятся в подробности обработчика не буду так как код прокомментирован достаточно.
Теперь поговорим о том как создать тень например нижнему меню вашего приложения. Реализуется это при помщи QuartzCore фреймворка. Подключить его в проект можно в разделе настроек вашего приложения Biuld Phases.
В h файле ваешго  viewcontroller – а прописываем инклуд #import
Теперь сам код который вы можете вставить например во viewdidload
 menu.layer.shadowColor = [UIColor blackColor].CGColor;
menu.layer.shadowOffset = CGSizeMake(0, 1);
menu.layer.shadowOpacity = 1;
menu.layer.shadowRadius = 3.0;
menu  в данном случае это UIBoutlet UITabbar, хотя по сути вы можете приминить тень к любому элементу на вашей view. Конечно же вы можете поиграть с цыфрами и посмотреть как меняется результат, а также изменить цвет тени, так как в моём варианте цвет чёрный.
И в заключении данной статьи хотелось бы показать ещё один метод позволяющий установить фоновую картинку на view вашего приложения
-(void) preperebg{
UIGraphicsBeginImageContext(self.view.frame.size);
[[UIImage imageNamed:@"bg.png"] drawInRect:self.view.bounds];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
}
bg.png – это картинка фона, желательно конечно же делать её под размер экрана мобильного устройства. в строке [[UIImage imageNamed:@"bg.png"] drawInRect:self.view.bounds]; – картинка отрисуется в размерах self.view. приложения, так что даже если она маленькая она всёравно заполнит собой все пространство.

IOS AlertView – реализация окна диалога

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


Посмотрим пример кода:
-(void) isneedRateDilog{
if([Utils checkshows]){
[[[UIAlertView alloc] initWithTitle:@»Оценить приложение»
message:@»Если вам понравилось приложение вы можете оставить оценку.»
delegate:self //делегат
cancelButtonTitle:nil // не делать кнопку отмены обычно она красного цвета
otherButtonTitles:@»Оценить»,@»Позже»,@»Никогда», nil] //кнопки
show]; //показать диалог сразу при вызове метода isneedRateDilog
}
}
И так мы задами название initWithTitle, текст сообщения message и три кнопки otherButtonTitles. Обратите внимание что делегатом мы указали self – тоесть обработка событий нажатия на кнопки будет в этом же классе.
Теперь посмотрим на обработчик событий:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
switch (buttonIndex) {
case 0://оценить
//сюда можно вставить любой другой код
break;
case 1://позже
break;
case 2://никогда
break;
}
}
Как видите всё достаточно прозаично: кнопки имеют индекс попорядку от нуля и до того количества кнопок – которое имеется у вас в диалоговом окне.

Полезные методы и функции для IOS разработчиков. Часть 2

В прошлой части полезных методов и функций я описал не все интересные примеры потому, что их очень много и теперь хочу продолжить эту тематику. Так как возможно это полезно вам и мне не даст забыть как это делается :)
Начать хотелось бы с полезного метода хранения некоторых пользовательских настроек в памяти мобильного устройства по средствам NSUserDefaults. Это некий класс с примитивными методами помогающими временно(на момент существования вашего приложения в пределах одной версии) хранить фактически любые данные. Начиная от просто строк до байтовых данных NSData. И так рассмотрим методы записи данных:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@"Строка любого содержания" forKey:@"some_str"];
В первой строке мы создаём объект класса NSUserDefaults что быработать с его методами. Во второй строке мы присваиваем значение ключу some_str в виде строки с произвольным содержимым. Теперь эта строка будет хранится пока мы не удалим приложение или не обновим его до следующей версии.  Как же теперь достать эти данные при необходимости? На самом деле очень просто:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *str = [userDefaults objectForKey:@"some_str"];
Заведома зная что у нас по этому ключу лежит строка я создал объект имено NSString. Хотя если вы например укажете там Int среда Xcode не выдаст вам ошибки так как объект содержащийся в userDefaults так сказать не индексируется. Но при использовании этого метода в период работы приложения будет ошибка и XCode напишет вам её в консоль. Поэтому надо быть поаккуратнее с подобыми операциями.
Для очистки значения по ключу достаточно присвоить ключу nil подобно тому как мы дели присвоение строки в первом листинге кода.
Ещё один не маловажный момент который может пригодится, а именно знать как выбирать между двумя разными stroyboard когда это необходимо.
Но делать такую проверку и выбор stroyboard необходимо в методе – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions класса AppDelegate.m вашего приложения, Поскольку выбрать его можно будет только до того как он станет для приложения по умолчанию, на лету это сделать нельзя. Допустим у вас уже есть stroyboard созданный XCode при создании нового приложения и вам необходимо добавить ещё один для запуска допустим на мобильных устройствах типа IPhone но с рейтина дисплеем. Создайте файл stroyboard и назовите его к примеру Rstoryboard.
И так открываем выше упомянутый метод и пишем слдеующий код:
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
UIStoryboard *storyBoard;
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
//проверим высоту экрана телефона
if(result.height == 1136){ //это нам подходит для определения рейтина дисплея
storyBoard = [UIStoryboard storyboardWithName:@"Rstoryboard" bundle:nil];//устанавливаем нужный нам Rstoryboard
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
}
Далее рассмотрим на примере код который позволит из вашего приложения открыть itunes со  страницей вашего приложения например для оценки или написания отзыва.
NSURL *appStoreURL = [NSURL URLWithString:@"ссылка на приложение"];
[[UIApplication sharedApplication] openURL:appStoreURL];
Фактически этот метод откроет safari но сам safari перенаправит пользователя на itunes. Ссылку на приложение легко сформировать нажав на стрелку возле Downlowd  на странице вашего приложения в Itunes, и выбрав copy link.

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


Я создал стандартный вид перехода от первого окна ко второму по средствам navigationController. Если скомпилировать проект мы увидим, что на первом окне уже появилась верхняя навигационная панель.



Теперь нам нужно добиться прозрачности навигационной панели в первом окне.
Для этого добавим следующий код в m файл нашего контроллера первого окна.
- (void)viewWillAppear:(BOOL)animated{
//прозрачный верхний бар
[self makeTransparentNavBar];
}
-(void) makeTransparentNavBar{
self.navigationController.navigationBar.translucent = YES;
const float colorMask[6] = {222, 255, 222, 255, 222, 255};
UIImage *img = [[UIImage alloc] init];
UIImage *maskedImage = [UIImage imageWithCGImage: CGImageCreateWithMaskingColors(img.CGImage, colorMask)];
[self.navigationController.navigationBar setBackgroundImage: maskedImage forBarMetrics:UIBarMetricsDefault];
//убираем тень
[self.navigationController.navigationBar setShadowImage: [[UIImage alloc] init]];
}
Сдесь я назначаю посути прозрачную картинку navigationBar-у и убираю тень. Вот как будет выглядеть первое окно при компиляции проекта, и ещё я добавил кнопку с помощью которой мы тоже осуществим переход на второе окно. Так же как и в случае с кнопкой Item я назначил ей push переход ко второму окну.

Во втором окне ситуация точно такая же. Верхняя панель прозрачная, но задача стоит спрятать навигационную панель только на первом окне. Для этого добавим следующий код в m файл второго контроллера:
- (void)viewWillAppear:(BOOL)animated{
//установим пустую картинку для панели
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
В данном методе мы убираем картинку с заднего плана тем самым navigationController сам установит нам дефолтный задний план. Теперь уберём название с навигационной панели первого окна и кнопку Item

Теперь можете скомпилировать проект и посмотреть как выглядит первое и второе окно.

IOS Программируем жесты с UIGestureRecognizer

Все мы знаешь, что в приложениях для IOS есть возможность создавать события на основе жестов на экране IPhone или IPad. В XCode мы можем сделать это с помощью Storyboard или же описать их программно. На мой взгляд особой разницы нет как это делать, но в данной статье я напишу как делать это программно. Для начала разберемся с тем какие бывают жесты.
  • UITapGestureRecognizer   – жест нажатия пальцем на экран
  • UIPinchGestureRecognizer  - жест "ущипнуть" экран
  • UIRotationGestureRecognizer - жест вращения пальцами по экрану
  • UISwipeGestureRecognizer - жест "скольжения" то есть протянули пальцем
  • UIPanGestureRecognizer - жест, который выглядит как перетаскивание
  • UILongPressGestureRecognizer - долгое удерживание пальца на экране
Все эти жесты помогают нам так или иначе разнообразить работу и интерфейс приложения. Рассмотрим простой пример когда необходимо использовать жест нажатия например на изображение UIImageView. Поскольку IBOutlet UIImageView не имеет стандартной возможности воспринимать действия на себе  -  пример будет достаточно полезным.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnImageView:)];
[image addGestureRecognizer:tap];
Tap- это объект распознователя жестов который я инициализировал с помощью указания себя в качестве передаваемого параметра в метод didTapOnImageView. Который отработает когда жест будет выполнен/или начат. Во второй строек я добавил его к объекту UIImageView image. Далее достаточно только создать метод didTapOnImageView как на примере:
-(void) didTapOnImageView:(UIGestureRecognizer*) recognizer {
//код который должен отработать
}
Почему я написал через слеш выполнен/или начат? Потому, что в методе  didTapOnImageView мы указали входящий параметр сам объект распознавания у которого можно получить его состояния и проверить их. Например таким условием:
if (recognizer.state == UIGestureRecognizerStateBegan)
//в данном случае проверка началось ли распознование жеста
При использовании UITapGestureRecognizer эта проверка встряли понадобится, но вот при UILongPressGestureRecognizer может быть к стати.
Список состояний которые можно проверить:
UIGestureRecognizerStatePossible - распознаватель еще не признал жест, но может быть сенсорным оценке событий. Это состояние по умолчанию.
UIGestureRecognizerStateFailed - распознаватель устанавливает этот статус когда жест не может быть выполнен

UIGestureRecognizerStateRecognized - распознаватель понял и распознал жест
UIGestureRecognizerStateBegan - распознавание жеста началось
UIGestureRecognizerStateChanged - распознаватель устанавливает этот статус когда жест был изменен и завершит распознавание на следующем цикле обработки

UIGestureRecognizerStateEnded  – распознавание жеста закончилось
UIGestureRecognizerStateCancelled - распознавание жеста было отменено

Манипулируя проверками этих состояний можно с точностью отловить, что происходит в тот или иной момент времени когда работает распознаватель жестов.
Рассмотрим ещё несколько опций которые могут быть использованы при работе с распознаванием жестов.  Например:
tap.minimumPressDuration = 1.0; //сколько секунд нужно удерживать палец на экране для распознавателя жеста UILongPressGestureRecognizer
[tap setNumberOfTouchesRequired:1]; //задает количество прикосновений которые необходимо сделать для распознавания жеста
Теперь рассмотрим еще один пример программной реализации жеста скольжения:
   UISwipeGestureRecognizer *swipetoleft = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(didSwipe)];
[swipetoleft setDirection:UISwipeGestureRecognizerDirectionLeft];
[optpodlozhka addGestureRecognizer:swipetoleft];
В данном примере появилась ещё одна строка [swipetoleft setDirection:UISwipeGestureRecognizerDirectionLeft]; Которая указывает направление жеста. Это свойство характерно для UISwipeGestureRecognizer. Этим я хочу сказать что для каждого вида жеста могут быть использованы разные свойства и настройки. Полный список которых можно посмотреть в UIGestureRecognizer Class Reference.

Проигрывание mp3 online через интернет в IOS.

Возможно вы когда нибудь задумывались о написании собственного приложения медиа плеера для проигрывания музыки из интернета или же просто прослушивания mp3 стрима. На самом деле реализовать такое приложение для iPhone не так уж и сложно. И так оснавная задача этой статьи объяснить как в приложении реализовать проигрывание mp3 файлов онлайн используя в качестве источника mp3 файл на удалённом сервере например адресс http://your.site.com/music.mp3
Необходимо создать проект и добавить в проект фреймворк MediaPlayer framework. Сделать это можно во вкладке Build phases вашего проекта в Xxode, нажав на плюсик в разделе Link Binary With Libraries. Он нужен нам для использования медиа плеера MPMoviePlayerController.

И так приступим к написанию кода для начала в h файле вашего метода нужно сделать импорт
#import
Далее в этом же файле давайте создадим свойство property для того что бы иметь доступ к объекту не только из данного класса:
@property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
Теперь переходим в m файл вашего контроллера и незабываем про
@synthesize moviePlayer;
Теперь можем добавить следующий код например в метод viewDidLoad
   NSString* resourcePath = @»http://your.site.com/music.mp3″; // url источника mp3 файла
NSURL *url = [NSURL URLWithString:resourcePath]; //формируем NSUrl
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url]; //инициализация плеера
//настройки оповещения системе от том что выполнить метод moviePlayBackDidFinish когда проигрывание закончится
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
//настройки плеера
moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
moviePlayer.shouldAutoplay = YES;
moviePlayer.view.userInteractionEnabled = YES;
//координаты и размер окошка плеера если хотим сделать не полноэкранный режим
[moviePlayer.view setFrame:CGRectMake(30, 30, 300, 20)];
moviePlayer.view.backgroundColor = [UIColor clearColor]; //прозрачный цвет фона за плеером вместо черного
[self.view addSubview:moviePlayer.view];
[moviePlayer setFullscreen:NO animated:NO]; //если указать например setFullscreen:YES то плеер запустится на полное окно приложения

Теперь при загрузке приложения сразуже запустится плеер и будет проигрывать ваш файл, но не забываем добавить ещё метод moviePlayBackDidFinish: смотрим код
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
if ([moviePlayer
respondsToSelector:@selector(setFullscreen:animated:)])
{
[moviePlayer.view removeFromSuperview]; //эта строка убирает с экрана сам плеер если хотите его оставить строку нужно удалить
}
}
Вот собственно все теперь вы умеете проигрывать музыку из интернета прямо в своём приложении. Более детальные настройки moviePlayer можно почитать в офицеальной SDK