iyOmSd/Title: Objc

[Objective-C] 스위프트 앱을 다시 만들어보기

냄수 2019. 8. 3. 18:20
반응형

안녕하세요 😄😄

 

기존에 만들었던 간단한 회원가입앱을 오브젝티브C로 다시 만들어 보려고해요

스위프트로 만든앱소개 링크는 아래를 참고하세요

실전을 공부하는게 되게 도움이 되거든요!!

 

처음부터 삐걱삐걱

오류가 많이났어요

클래스 만드는 방법을 몰라서요... 스위프트랑 달라서 헷갈리더라구요

 

처음에 할땐 저 처럼 어려워 하시는 분들을 위해 클래스를 한번 만들어 볼게요!

 

 

우선 파일을 만들거에요

저는 처음에 오른쪽끝에있는 Objective-C File로 만들었어요...

클래스파일하나 만드는거니까 이걸로해야지!! 하고 만들었지만

오류만 나고 헤맷어요...

 

저처럼 헤매시지 마시고 보통 만들듯이!! Cocoa Touch Class를 클릭하세요

 

오브젝티브C로 만들거니까 언어설정해주시구요

클래스는 NSObject로 할거에요

이게 보통 클래스파일로 쓰나봐요

 

제가 만드려는 앱에 싱글톤을 이용해서 정보를 간단하게 주고받을건데요

새로운 언어로 하려니까 모르겟더라구요

되게 삽집을 많이한 끝에

dispatch_once 라는 것을 알았어요

요놈이 싱글톤 만들어주는 역할을해요

dispatch_once는 App LifeCycle에서 단 한번만 실행된다고 해요

dispatch_once_t 와함께 쓰이는데 얘는 dispatch_once가 실행되었는지 체크해주는 역할이레요

 

 

UserInfo.h

@interface UserInfo : NSObject


@property NSString *userId;
@property NSString *userPw;
@property NSString *userBirth;
@property NSString *userMemo;

+ (instancetype)getInstance;

@end

싱글톤으로 저장할 변수들을 만들어주고

getInstance를 통해서 싱글톤 객체를 사용할거에요

라고 .h파일에 선언해주고

 

 

UserInfo.m

#import "UserInfo.h"

@implementation UserInfo

//인스턴스객체 생성
+ (instancetype)getInstance{
    static dispatch_once_t pred;
    static UserInfo *shared = nil;
    
    dispatch_once(&pred, ^{
        shared = [[UserInfo alloc] init];
    });
    
    return shared;
}


@end

이런 방식으로 싱글톤객체를 생성해서 쓸수있어요

더 좋은방법이 있을 수 도있어요

오브젝티브씨로 처음 사용해보는 싱글톤이에요..! 부족한점이 많을지도 몰라요

 

 

 

 

 

 

 

 

처음 화면

 

💡기능은

Sign Up 버튼클릭시 간단한 정보를 입력하는 화면으로가고

Login 버튼클릭시 가지고있는 싱글톤 객체와 비교해서 로그인을 할거에요

 

 

ViewController.m

#import "ViewController.h"
#import "UserInfo.h"

@implementation ViewController {
    
    __weak IBOutlet UITextField *idTextField;
    __weak IBOutlet UITextField *pwTextField;
}

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

- (IBAction)loginBtnClick:(id)sender {
    
    //로그인 성공시 다음화면
    if( [self excuteLoginWithId: idTextField.text pw: pwTextField.text] ){
        UIViewController *nextVC = [[self storyboard] instantiateViewControllerWithIdentifier: @"Info"];
        [self presentViewController: nextVC animated:true completion:nil];
    }
    
}

// 로그인 확인
- (Boolean)excuteLoginWithId: (NSString *) i pw: (NSString *) p {
    
    if( [[UserInfo getInstance] userId] == idTextField.text && [[UserInfo getInstance] userPw] == pwTextField.text ){
        return true;
    }else{
        return false;
    }
}

@end

 

로그인했을때 아이디비번이 가지고있는 싱글톤객체와 정보가 일치하는지

일치시 다음화면으로 이동하도록 했어요

이동하는 ViewController의 Storyboard ID는 Info에요

 

 

 

 

 

두번째화면

위의 사진은 Sign Up버튼을 누르면 나오는 화면이에요

 

SignUpViewController.m

#import "SignUpViewController1.h"
#import "UserInfo.h"

@implementation SignUpViewController1{
    
    __weak IBOutlet UITextView *textView;
    __weak IBOutlet UIImageView *imageView;
    __weak IBOutlet UITextField *idTextField;
    __weak IBOutlet UITextField *pwTextField;
    __weak IBOutlet UITextField *pw2TextField;
    
    UIImagePickerController *imagePicker;
    
    UserInfo *info;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    info = [UserInfo getInstance];
    imagePicker = [[UIImagePickerController alloc]init];
    imagePicker.delegate = self;
    
    
}


- (IBAction)nextBtnClick:(UIButton *)sender {
    
    if([self emptyCheck]){
        
        //Alert생성
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"확인" message:@"빈칸이나 비밀번호를 확인해주세요" preferredStyle: UIAlertControllerStyleAlert];
        
        UIAlertAction * ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
        
        [alert addAction:ok];
        [self presentViewController:alert animated:YES completion:nil];
        
    }
    
    else{
        info.userId = idTextField.text;
        info.userPw = pwTextField.text;
        info.userMemo = textView.text;
        
        NSLog(@"%@, %@", info.userId, info.userPw);
        
        //이미 지정해둔 manual segue
        [self performSegueWithIdentifier:@"signUp" sender:self];
    }
}
- (IBAction)cancelBtnClick:(UIButton *)sender {
    
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)imgBttClick:(id)sender {
    
    imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    imagePicker.allowsEditing = true;
    
    [self presentViewController:imagePicker animated:YES completion:nil];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info{
    
    //key값으로 이미지 가져오기
    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
    if(image){
        imageView.image = image;
    }
    [self dismissViewControllerAnimated:YES completion:nil];
    
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    [self dismissViewControllerAnimated:YES completion:nil];
}

//빈칸이나 비밀번호 같은지 확인
- (Boolean)emptyCheck{
    if(idTextField.text == nil)
        return true;
    if(pwTextField.text == nil)
        return true;
    if(pwTextField.text != pw2TextField.text){
        return true;
    }
    
    return false;
}

@end

 

💡기능은

아이디와 비밀번호를 입력하고 한번더 입력하는 창이있구요

Next버튼 클릭시 

이셋중 하나라도 안쓰거나 비밀번호가 다른경우

Alert를 이용해서 확인창을 띄울거에요

다 입력했다면

싱글톤객체에 입력한 정보를 저장하고 다음화면으로 넘어가도록 했어요

Cancel버튼 클릭시

Modal로 띄운 뷰컨트롤러를 종료시킬거에요 그러면 처음화면으로 돌아갈거에요

image의 빈칸을 클릭하면 imagePicker을 이용해서 앨범의 이미지를 골라서 보여줄 수 있어요

 

 

 

이제 위의 코드를 하나하나 분석해 볼게요!!

 

 

 

우선 emptyCheck함수는 간단해요

스토리보드에 있는 idTextField와 pwTextField를 가져와서 빈칸인지 확인하고

pwTextField 와 pw2TextField의 내용이 같은지 확인하는 코드에요

 

그리고 viewDidLoad에서 실행될때

info 라는 인스턴스 객체를 만들어 줬어요

나중에 싱글톤을 이용해서 정보를 저장하려고 만들어 놨어요

 

 

Next 버튼을 누를 때 동작이에요

앞에서 정의한 emptyCheck의 함수의 결과를 받아서실행 되도록 만들었어요

 

제 코드가 좋은코드는 아닐 수도있어요... 저는 ㅇ..아..직... ㅂ..부족해요...

 

Alert를 생성하고 Action을 달아주는 코드가 포함되어있어요

스위프트를 해보았다면 함수를 쓰시는데 익숙하실거에요

 

입력한 정보에 이상이 없다면

앞에서 만든 info변수로 정보를 저장하고

 

미리 스토리보드에 manual segue에 identifier로 signUp을 지정해둬서

를 이용해서 다음 화면으로 넘어갈거에요

 

그리고 NSLog라고 보이네요

Xcode에서 로그로 확인할 수 있어요

Swift에서 print의 기능을 하는거라고 보시면되요

다른점은 @을 사용해서 변수를 참조하네요

 

 

 

 

이건 Cancel을 누를때의 동작이에요

간단하게 dismiss를 통해서 모달로띄운 창을 꺼버리는 거에요

 

 

 

한번 실행해 볼게요

 

 

 

제대로 작동하는 것을 볼 수 있어요!!

 

 

다음은 ImagePicker사용입니다

해당 .h파일로 가서 imagepicker을 사용할 수 있게 해줘야해요

 

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface SignUpViewController1 : UIViewController <UIImagePickerControllerDelegate,UINavigationControllerDelegate> {
    
}

@end

NS_ASSUME_NONNULL_END

헤더파일 interface옆에 위에와같이 <UIImagePickerControllerDelegate,UINavigationControllerDelegate>를 추가해줍니다

이렇게하면 Swift에서처럼 delegate를 사용하여 편하게 쓸 수 있어요

다음으로는 위 코드처럼 viewDidLoad에서 delegate를 설정해줄거에요

 

저는 이미지뷰위에 투명버튼을 올려서

그 버튼을 클릭하면 ImagePicker가 작동하도록 구현 했어요

 

sourceType설정해주고

allowsEditing설정해주고

present 하면 ImagePicker가 뜹니다.

 

[info objectForKey:UIImagePickerControllerEditedImage]를 이용해서 imagepicker의 이미지를 가져올 수 있어요

 

 

 

 

 

 

 

 

세번째 화면

 

Next를 누르면 나타나는 화면이에요

 

💡기능은

datePicker에서 날짜를 선택하고 finish를 누르면 싱글톤 객체에 저장되요

Cancel을 누르면 모달로띄운 뷰컨트롤러가 종료되요 -> 전 화면이아닌 처음 로그인화면으로 돌아가요!!

 

SignUpViewController2.m

#import "SignUpViewController2.h"
#import "UserInfo.h"

@implementation SignUpViewController2 {
    
    __weak IBOutlet UIDatePicker *datePicker;
}

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

- (NSString *)formatWithDate: (NSDate *)date{
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

//  여기서는 제가원하는 방식의 포맷을 이용할거기때문에 생략했어요   
//  formatter.dateStyle = NSDateFormatterLongStyle;

//  시간 데이터는 사용하지 않을거기 때문에 No
    formatter.timeStyle = NSDateFormatterNoStyle;
    formatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:@"ko_KR"];
    
    //원하는 포맷으로 날짜 변환
    formatter.dateFormat = @"yyyy-MM-dd";
    NSString *s = [formatter stringFromDate:date];
    
    return s;
}

- (IBAction)finishBtnClick:(UIButton *)sender {
    
    //싱글톤 객체에 생일저장
    UserInfo.getInstance.userBirth = [self formatWithDate:datePicker.date];
    
    NSLog(@"%@", [self formatWithDate:datePicker.date]);
}

- (IBAction)cancelBtnClick:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

@end

 

 

코드를 자세히 볼게요

 

중요한건 하나밖에 없는거 같네요

 

DatePicker에서 가져온 Date정보를 제가원하는 입맛에 맞게 바꿔줄 함수만 보면 될 거 같아요

 

DatePicker을 변환할땐

기본적으로

1. NSDateFormatter객체를 만들어주고

2. dateStyle or dateFormat

3. timeStyle

4. locale

을 설정해주면 되요

 

여기서 2번 3번은 스타일에 따라서 나타나는 형식이 달라요

formatter.dateStyle = NSDateFormatterMediumStyle;

결과-> 2019. 7. 3.

 

formatter.dateStyle = NSDateFormatterLongStyle;

결과-> 2019년 8월 3일

 

내 마음대로 형식을 바꾸고싶다하면 2번대신에 dateFormat

formatter.dateFormat = @"yyyy-MM-dd";

처럼 하면되요

 

마지막에 [formatter stringFromDate] 를이용해서 NSString형으로 바꿀 수 있어요

 

 

 

 

 

 

 

네번째 화면

 

💡기능

싱글톤객체에 저장되어있는 정보를 보여주는 기능 하나에요 너무 간단하죠

 

 

코드한번 볼게요

 

#import "LoginViewController.h"
#import "UserInfo.h"

@implementation LoginViewController{
    
    __weak IBOutlet UILabel *idLabel;
    __weak IBOutlet UILabel *pwLabel;
    __weak IBOutlet UILabel *birthLabel;
    __weak IBOutlet UITextView *textView;
    __weak IBOutlet UIButton *cancelBtn;
    
    UserInfo *user;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    user = [UserInfo getInstance];
    [self setUserInfo];
    [self designTextView];
}

- (void)setUserInfo {
    idLabel.text = user.userId;
    pwLabel.text = user.userPw;
    birthLabel.text = user.userBirth;
    textView.text = user.userMemo;
}

- (void)designTextView {
    textView.layer.borderWidth = 1.0;
    textView.layer.cornerRadius = 7.0;
    textView.layer.borderColor = UIColor.blackColor.CGColor;
}
- (IBAction)cancelBtnClick:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

@end

 

Swift를 해봤다면 이코드는 익숙하고 쉬울거에요

오브젝티브C로 디자인도 해보고 싶어서 해봤어요

 

 

디자인을 적용해서 실행한 화면이에요

 

TextView에 text를 설정할때 여러 글자를 합치고싶다면

textView.text = [@"가나다라 1234"stringByAppendingString:user.userMemo];

처럼 stringByAppendingString를 이용하면

결과로 '가나다라 1234'뒤에 userMemo에 저장된 값이 출력될거에요

 

 

 

 

 

처음에 오브젝티브C앱을 만드려고 시작할때 빌드부터 애먹었엇는데

어느순간 익숙하게 코드를 찾아서 치고 있었어요

 

역시 시작이 반인가봐요 ㅎㅎ

 

이렇게 간단한 앱을 만들어 봄으로써 오브젝티브C에 좀더 적응해봤어요

 

 

스위프트 버전은 다른 곳에 정리해두어서 보고싶다면 참고하시면 좋을것 같아요

아예 똑같진않고 조금 다른 부분이 있을 수 있어요

https://blog.naver.com/are34/221459515556

반응형