Objective-C로 TodoList만들어보기

AekT·2022년 8월 3일
3
post-thumbnail

Why?

요즘 여유시간이 남기도하고 심심하니 뭔가를 할까, 생각하다가 머리 한 구석에서 Objective-C가 떠올랐다. 어디에서는 레거시로 남아있기도하니 readOnly할 수 있을 정도면 괜찮을거같아서 한 번 해보려고 한다.

프로젝트 생성

Project이름은 Todo + Objc로 TodObjc로 지어봤다.
Interface는 Storyboard, Language는 Objective-C로 설정하고 프로젝트를 생성한다.

설계

Objc를 써보고 익숙해지는 것이 메인 목표이니 디자인 패턴 없이 ViewController에 로직 몰아넣고 해보려고 한다.

Todo Class

@interface Todo : NSObject

@property (strong, nonatomic) NSString *title;
@property (nonatomic) BOOL isCompleted;

- (instancetype) init:(NSString*)title;

@end
#import "Todo.h"

@implementation Todo

- (instancetype)init:(NSString*)title {
    self = [super init];
    if (self != nil) {
        _title = title;
        _isCompleted = false;
    }
    return self;
}

@end

Todo class를 만들기 위해서 Todo.h파일에서 @interface로 property들이랑 init을 정의해놓고 Todo.m 파일에서 @implementation으로 Todo를 구현해준다.

Todo DB

#import <Foundation/Foundation.h>
#import "Todo.h"

NS_ASSUME_NONNULL_BEGIN

@protocol TodoDatabase <NSObject>

@required
- (void) saveTodo:(Todo*)todo;
- (NSArray*) readAll;
- (void) updateAt:(NSInteger*)at :(Todo*)todo;
- (void) deleteTodo:(Todo*)todo;
- (void) deleteAt:(NSInteger*)at;

@end

NS_ASSUME_NONNULL_END

TodoDatabase Protocol을 만들고,

#import <Foundation/Foundation.h>
#import "TodoDatabase.h"

NS_ASSUME_NONNULL_BEGIN

@interface InMemoryTodoDatabase : NSObject <TodoDatabase>

@property (nonatomic) NSMutableArray<Todo *> *items;

- (instancetype) init;

@end

NS_ASSUME_NONNULL_END

TodoDatabase를 confirm하는 InMemoryTodoDatabase header를 만들고,

#import "InMemoryTodoDatabase.h"

@implementation InMemoryTodoDatabase

- (instancetype)init {
    self = [super init];
    if (self != nil) {
        _items = [NSMutableArray array];
    }
    return self;
}

- (void)saveTodo:(nonnull Todo *)todo {
    [_items addObject:todo];
}

- (nonnull NSArray *)readAll {
    return _items;
}

- (void)updateAt:(nonnull NSInteger *)at :(nonnull Todo *)todo {
    [_items replaceObjectAtIndex:(NSUInteger)at withObject:todo];
}

- (void)deleteAt:(nonnull NSInteger *)at {
    [_items removeObjectAtIndex:(NSUInteger)at];
}

- (void)deleteTodo:(nonnull Todo *)todo {
    [_items removeObject:todo];
}

@end

InMemoryTodoDatabase 구현을 해서 InMemory로 Todo 데이터들을 관리하는 class를 만든다.

Todo 추가

- (IBAction)addButtonDidTap:(UIBarButtonItem *)sender {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"TODO" message:@"할 일을 입력해주세요" preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler:nil];
    
    __weak typeof(self) weakSelf = self;
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"취소" style:UIAlertActionStyleCancel handler:nil];
    UIAlertAction *addAction = [UIAlertAction actionWithTitle:@"추가" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [weakSelf.db saveTodo:[[Todo alloc] init:alert.textFields[0].text]];
        [weakSelf todoListRefresh];
    }];
    [alert addAction:cancelAction];
    [alert addAction:addAction];
    [self presentViewController:alert animated:true completion:nil];
}

Navigation Bar에 있는 plus버튼을 누르면 TextField를 가진 Alert가 나오면서 Todo를 추가할 수 있게 했다.

Todo 완료 여부

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    Todo *todo = _todoList[indexPath.row];
    todo.isCompleted = !todo.isCompleted;
    [_db updateAt:indexPath.row :todo];
    [self todoListRefresh];
}

cell을 터치했을때 isCompleted의 값을 반대로 바꾸게 해서 완료 여부를 수정할 수 있다.

Todo 삭제

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    __weak typeof(self) weakSelf = self;
    
    UIContextualAction *deleteAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"삭제" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
        [weakSelf.db deleteAt:indexPath.row];
        [weakSelf todoListRefresh];
    }];
    deleteAction.backgroundColor = UIColor.redColor;
    
    return [UISwipeActionsConfiguration configurationWithActions:@[deleteAction]];
}

Trailing Swipe로 todo를 삭제할 수 있게 했다.

결과물

마무리

Objective-C... 첫인상은 악명대로 상당히 난해해보였다. @interface니 @implementation이니 많이 생소하였다. 함수는 []로 감싸서 써야했고 Protocl은 <>안에 넣어야 confirm되는 등 낯선 점이 꽤나 있었는데 그래도 일단은 프로그래밍 언어이니 만큼 계속 읽고 쓰고 하다보니 어느정도 감은 잡은거 같다. 깃허브에 있는 Objc로 된 레포 몇개 열어봤을 때 읽혀졌으니 나름 목적은 달성한듯 하다. 그래도 조만간 정리를 해놔야겠다..

Github

https://github.com/baekteun/TodObjc

profile
으악

0개의 댓글