Translate/Parse

Parse 튜토리얼, 이미지 저장하기 1/2

KraZYeom 2013. 2. 7. 08:27
반응형

원문 : Saving Images


사용자들이 사진을 찍고 Parse에 직접 사진을 올리게 해주는 앱을 만드는 방법을 배운다.

이 튜토리얼의 소스코드 다운로드 링크: .zip | GitHub

사진 앱은 강력하다. 자신의 사진앱을 만들기를 원한다면, Parse를 사용하라. Parse는 파일 저장하기, 파일 찾기 그리고 사용자와 연결하기를 포함한 모든 백-엔드를 다룰 수 있다.

이 튜토리얼에서는 Parse 플랫폼에 여러분의 사진을 서버 사이드 코딩 걱정없이 저장할 수 있는 방법을 보여줄 것이다.

완료된 앱은 아래 이미지와 비슷하게 보일 것이다. 우선 더 나은 아이디어를 얻기 위해 샘플 데모앱을 확인하고 구동해보는 것을 추천한다.




설정하기

view-based 프로젝트로 시작할 것이다. 우선 ViewController.xib에 UINavigationBar과 두 개의 UIBarButtonItem(카메라/새로고침)을 추가한다. 그리고 UIScrollView을 가운데로 배치시킨다. 최종 nib파일의 모습은 다음과 비슷할 것이다.



마쳤으면, IBOutlet을 생성하고 UIScrollView와 연결시킨다. 뿐만아니라 두 개의 IBAction 메소드를 각각 카메라 버튼과 새로고침 버튼에 연결시킨다.

IBOutlets과 IBActions이 올바르게 연결되었는지 확인하라. File's Owner를 클릭하고 Connections 인스팩터를 열어서 확인할 수 있다.(스크린샷 참조)

또한, 올바른 프레임워크를 가져오기를(import)해야 한다. 필수 프레임워크: Parse.framework,AudioToolbox.frameworkCFNetwork.frameworklibz1.1.3.dylibMobileCoreServices.framework,QuartzCore.frameworkSecurity.frameworkSystemConfiguration.frameworkUIKit.frameworkFoundation.frameworkCoreGraphics.framework.



마지막으로, 액티비티 인디게이터 또는 스피너를 나타내기 위해 MBProgressHUD  를 사용할 것이다. MBProgressHUD를 다운로드한다. 그리고 Xcode 프로젝트에 MBProgressHUD.h와 MBProgressHUD.m를 추가한다.

사용자 생성하기

클라우드에 올라간 각각의 파일은 PFUser와 연결될 수 있다. 이 튜토리얼에서는 가입을 위해서 거짓 username과 password를 사용할 것이다. 여기 https://www.parse.com/docs/ios_guide#users 에서 PFUsers에 관해 더 배울수 있다.

앱 델리게이트에서 처음에 아래 코드를 추가한다.

PFUser *currentUser = [PFUser currentUser];
    if (currentUser) {
        [self refresh:nil];
    } else {
        // 거짓 username 와 password
        PFUser *user = [PFUser user];
        user.username = @"Matt";
        user.password = @"password";
        user.email = @"Matt@example.com";
         
        [user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            if (!error) {
                [self refresh:nil];
            } else {
                [PFUser logInWithUsername:@"Matt" password:@"password"];
                [self refresh:nil];
            }
        }];
    }
}

이것은 시스템에 사용자가 현재 로그인 되어 있는지 확인한다. 이전에 가입했거나 로그인 되어 있으면 미리 저장되거나 캐쉬된 사용자를 사용한다. 만약 디스크에 캐쉬된 사용자가 없으면, 하나 생성한다.

다시말하면 두 가지의 시나리오에 대한 설명이 필요하다: username이 있을 경우, 로그인을 하면 된다.

헤더 파일 설정하기

구현하기 전에, 헤더 파일을 설정해야한다. 처음으로 메소드를 참조 가능하게 하기위해 ViewController.h 에 <Parse/Parse.h> 를 임포트한다. MBProgressHUD.h 는 엑티비디 인디게이터를 위해 그리고 stdlib.h 는 램덤생성기를 위해서 임포트한다. 또한 델리게이트 메소드를 사용하기 위해서 UINavigationControllerDelegateUIImagePickerControllerDelegate 그리고 MBProgressHUDDelegate 프로토콜을 적용한다. UINavigationControllerDelegate 는 UIImagePickerController 가 UINavigationController 의 서브클래스이기 때문에 추가한다.

다음으로, 인스턴스 변수 photoScrollViewallImagesHUD, 그리고 refreshHUD 추가한다. photoScrollView는 사진을 보여주는 스크롤 뷰를 참조한다. allImages 는 사진을 담고 있는 배열을 참조한다. 그리고 나머지 2개는 곧 사용할 HUDs를 참조한다. 

마지막으로, 오늘 사용할 5개 메소드를 추가한다. 

//ViewController.h
 
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "MBProgressHUD.h"
#include <stdlib.h>
 
@interface ViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate, MBProgressHUDDelegate>
{
    IBOutlet UIScrollView *photoScrollView;
    NSMutableArray *allImages;
     
    MBProgressHUD *HUD;
    MBProgressHUD *refreshHUD;
}
 
- (IBAction)refresh:(id)sender;
- (IBAction)cameraButtonTapped:(id)sender;
- (void)uploadImage:(NSData *)imageData;
- (void)setUpImages:(NSArray *)images;
- (void)buttonTouched:(id)sender;

HUD 델리게이트와 Image 사이즈 재조정 메소드 구현하기

HUD 델리게이트 메소드 구현을 해야한다.

- (void)hudWasHidden:(MBProgressHUD *)hud {
    // 숨겨질때 HUD를 화면에서 삭제하기
    [HUD removeFromSuperview];
    HUD = nil;
}

올바른 시간에 메인 뷰에서 HUD를 삭제한다. 

UIImagePickerController 사용하기

다바이스에서 사진을 업로드 할 수 있어야 한다. 만약 카메라를 사용할 수 있으면 사진을 찍고 업로드 한다. 그렇지 않으면, 디바이스 또는 시뮬레이터에 있는 이미지 파일을 올릴 것이다. 5개의 자유롭게 사용할 수 있는 이미지가 있다.

첫 번째 스텝은 cameraButtonTapped 소드에서 UIImagePickerController 를 생성하는 것이다. 우선 카메라 소스가 사용가능한지 검증부터 해야한다. 그리고 UIImagePickerController 객체를 생성한다. 소스 타입과 델리게이트를 설정해야한다.

if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera] == YES){
        // 이미지 피커 컨트롤러 생성
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
         
        // 카메라 소스 설정
        imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;
         
        // Delegate is self
        imagePicker.delegate = self;
         
        // 이미지 피커 보여주기
        [self presentModalViewController:imagePicker animated:YES];
    }

카메라 미지원 디바이스를 다루기 전에 이미지 피커 델리게이트 메소드를 마쳐야 한다. 반환되는 JPEG를 크기를 재조정하고 압축한다. 그리고 uploadImage 메소드를 호출하고 imageData 를 전달한다.


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // 인포 딕셔너리(info Dictionary)에서 크롭되지 않은 이미지에 접근한다.
    UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
     
    // 컨트롤러를 닫는다.
    [picker dismissModalViewControllerAnimated:YES];
     
    // 이미지 크기 재조정
    UIGraphicsBeginImageContext(CGSizeMake(640, 960));
    [image drawInRect: CGRectMake(0, 0, 640, 960)];
    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();  
 
    // 이미지 업로드
    NSData *imageData = UIImageJPEGRepresentation(image, 0.05f);
    [self uploadImage:imageData];
}

다음으로 카메라가 없는 디아이스와 시뮬레이터에 대한 설명이 필요하다. 기존에 있는 UIImage 를 랜덤하게 선택한다. 크기를 재조정하고 높은 압축 퀄리티의 NSData 로 변환한다. 그리고 imageData 를  uploadImage 메소드에 전달한다.

else{
    // 카메라가 없는 기기
    UIImage *image;
    int r = arc4random() % 5;
    switch (r) {
        case 0:
            image = [UIImage imageNamed:@"ParseLogo.jpg"];
            break;
        case 1:
            image = [UIImage imageNamed:@"Crowd.jpg"];
            break;
        case 2:
            image = [UIImage imageNamed:@"Desert.jpg"];
            break;
        case 3:
            image = [UIImage imageNamed:@"Lime.jpg"];
            break;
        case 4:
            image = [UIImage imageNamed:@"Sunflowers.jpg"];
            break;
        default:
            break;
    }
 
    // 이미지 크기 재조정
    UIGraphicsBeginImageContext(CGSizeMake(640, 960));
    [image drawInRect: CGRectMake(0, 0, 640, 960)];
    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();  
         
    NSData *imageData = UIImageJPEGRepresentation(image, 0.05f);
    [self uploadImage:imageData];
}

사진 업로드하기

PFUsers 에 PFFile 어트리뷰트를 가진 PFObject 를 연결할 것이다.  그리고 PFObject 를 클라우드에 저장한다. 더 많은 사용자 정의를 하고 싶다면, 블럭안에서 모든 에러를 캐취할 수 있다는 것을 명심해라.

percentDone 파라미터로 두 번째 블럭에서 HUD의 진행률을 갱신할 수 있다.

uploadImage 메소드에서 다음과 같이 구현한다.

PFFile *imageFile = [PFFile fileWithName:@"Image.jpg" data:imageData];
     
// 여기에 HUD 생성 (예제 코드 참조)
     
// PFFile 저장
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
    if (!error) {
        // 지난 HUD 숨기기, 완료된 HUD 보여주기 (예제 코드 참조)
             
        // PFFile으로 PFObject를 만들고 현재 사용자와 연결하기.
        PFObject *userPhoto = [PFObject objectWithClassName:@"UserPhoto"];
        [userPhoto setObject:imageFile forKey:@"imageFile"];
             
        // 보안 목적을 위한 현재 유저에게 엑세스 컨트롤 목록 설정하기
        userPhoto.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
             
        PFUser *user = [PFUser currentUser];
        [userPhoto setObject:user forKey:@"user"];
             
        [userPhoto saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            if (!error) {
                [self refresh:nil];
            }
            else{
                // 상세 실패 로그
                NSLog(@"Error: %@ %@", error, [error userInfo]);
            }
        }];
    }
    else{
        [HUD hide:YES];
        // 상세 실패 로그
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
} progressBlock:^(int percentDone) {
    // 프로그래스 스피너 업데이트. percentDone는 0부터 100사이
    HUD.progress = (float)percentDone/100;
}];

PFObject 저장 후, 성공 콜백으로 서버에 호출하고 이미지를 다운로드 할 수 있게 새로고침 메소드를 호출할 수 있다.  

반응형