Objective-C: фото из галереи/камеры и отправка по HTTP

unnamed

В этом посте рассматривается пример получения изображения из галереи и камеры телефона. Затем отправим полученное изображение в бэкэнд.

Шаг 1.

Добавляем три значения в Info.plist:

Screen Shot 2017-04-23 at 15.04.05

Первая строка нужна для возможности выбора изображения из галереи. Вторая строка — для камеры. Третья строка нужна для возможности подключения к серверу по не HTTPS.

Шаг 2.

Рисуем интерфейс.

UILabel *imageStatusLabel;
UIImageView *imageView;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self buildView];
}

- (void) buildView {
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    
    UIView *imageContainerView = [[UIView alloc] initWithFrame:CGRectMake(
                                                                          0,
                                                                          0,
                                                                          screenWidth,
                                                                          450)];
    imageContainerView.layer.borderColor = [UIColor grayColor].CGColor;
    imageContainerView.layer.borderWidth = 1.0f;
    [self.view addSubview:imageContainerView];
    
    CGFloat currentY = 30;
    
    imageStatusLabel = [[UILabel alloc] initWithFrame:CGRectMake(
                                                                30,
                                                                currentY,
                                                                imageContainerView.frame.size.width - 60,
                                                                20)];
    imageStatusLabel.text = @"No image";
    imageStatusLabel.textAlignment = NSTextAlignmentCenter;
    [imageContainerView addSubview:imageStatusLabel];
    currentY += imageStatusLabel.frame.size.height + 20;
    
    UIButton *selectImageButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                      (screenWidth - 200)/2,
                                                                      currentY,
                                                                      200,
                                                                      30)];
    [selectImageButton setTitle:@"Select image" forState:UIControlStateNormal];
    selectImageButton.showsTouchWhenHighlighted = true;
    selectImageButton.backgroundColor = [UIColor grayColor];
    [selectImageButton addTarget:self action:@selector(selectImage:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:selectImageButton];
    currentY += selectImageButton.frame.size.height + 20;
    
    UIButton *takePhotoButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                             (screenWidth - 200)/2,
                                                                             currentY,
                                                                             200,
                                                                             30)];
    [takePhotoButton setTitle:@"Take photo" forState:UIControlStateNormal];
    takePhotoButton.showsTouchWhenHighlighted = true;
    takePhotoButton.backgroundColor = [UIColor grayColor];
    [takePhotoButton addTarget:self action:@selector(takePhoto:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:takePhotoButton];
    currentY += takePhotoButton.frame.size.height + 20;

    
    imageView = [[UIImageView alloc] initWithFrame:CGRectMake(
                                                              30,
                                                              currentY,
                                                              imageContainerView.frame.size.width - 60,
                                                              200)];
    imageView.backgroundColor = [UIColor grayColor];
    [imageContainerView addSubview:imageView];
    currentY += imageView.frame.size.height + 20;
    
    UIButton *sendButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                      (screenWidth - 200)/2,
                                                                      currentY,
                                                                      200,
                                                                      30)];
    [sendButton setTitle:@"Send image" forState:UIControlStateNormal];
    sendButton.showsTouchWhenHighlighted = true;
    sendButton.backgroundColor = [UIColor grayColor];
    [sendButton addTarget:self action:@selector(sendImage:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:sendButton];
}

Изначальный вид:

Screen Shot 2017-04-23 at 14.56.43

Шаг 3.

Получение изображения.

- (void) selectImage:(UIButton *) sender {
    NSLog(@"selectImage");
    UIImagePickerController *pickerViewController = [[UIImagePickerController alloc] init];
    pickerViewController.allowsEditing = YES;
    pickerViewController.delegate = self;
    [pickerViewController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
    [self presentViewController:pickerViewController animated:YES completion:nil];
}

- (void) takePhoto:(UIButton *) sender {
    NSLog(@"takePhoto");
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        UIImagePickerController *pickerViewController =[[UIImagePickerController alloc]init];
        pickerViewController.allowsEditing = YES;
        pickerViewController.delegate = self;
        pickerViewController.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self presentViewController:pickerViewController animated:YES completion:nil];
    } else {
        UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Error" message:@"Camera is not available" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
        [alert addAction:defaultAction];
        [self presentViewController:alert animated:YES completion:nil];
    }
}

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [self dismissViewControllerAnimated:picker completion:nil];
    UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
    imageView.image = image;
    imageStatusLabel.text = @"Image imported into the app";
}

selectImage — получения изображения из галереи. takePhoto — получение изображения из камеры. Камера, конечно, не будет работать в симуляторе. Логика selectImage и takePhoto общая: вызвать UIImagePickerController и получить изображение когда пользователь выберет одно. В наш класс надо добавить 2 делегата:

@interface ViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

Пример:

unnamed

Шаг 4.

Отправка изображения по HTTP по методу POST. Я записал изображение в тело HTTP. Мы также можем записать изображение в одном из POST полей.

- (void) sendImage:(UIButton *) sender {
    NSLog(@"sendImage");
    
    imageStatusLabel.text = @"Image is uploading";
    
    UIImage *yourImage= imageView.image;
    NSData *imageData = UIImagePNGRepresentation(yourImage);
    NSString *postLength = [NSString stringWithFormat:@"%d", (int)[imageData length]];
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setHTTPMethod:@"POST"];
    [request setURL:[NSURL URLWithString:@"http://{SERVER_ADDRESS}/upload.php"]];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:imageData];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {
                                      if (data == nil) {
                                          [self printCannotLoad];
                                      } else {
                                          [self printSuccess];
                                      }
                                  }];
    [task resume];
}

- (void) printCannotLoad {
    dispatch_sync(dispatch_get_main_queue(), ^{
        imageStatusLabel.text = @"Cannot upload";
    });
}

- (void) printSuccess {
    dispatch_sync(dispatch_get_main_queue(), ^{
        imageStatusLabel.text = @"Successfully uploaded";
    });
}

Шаг 5.

Как видите мы отправляем изображение по адресу http://{SERVER_ADDRESS}/upload.php . Для целей тестирования на стороне сервера можно добавить подобную строку в upload.php:

<?php file_put_contents("image.png", file_get_contents("php://input")); ?>

Шаг 6.

Тестирование на симуляторе и реальном устройстве.

Screen Shot 2017-04-23 at 14.55.09

Проект на GitHub.

 

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Картинка профиля Doszhan Kalibek

Doszhan Kalibek