요즘 여유시간이 남기도하고 심심하니 뭔가를 할까, 생각하다가 머리 한 구석에서 Objective-C가 떠올랐다. 어디에서는 레거시로 남아있기도하니 readOnly할 수 있을 정도면 괜찮을거같아서 한 번 해보려고 한다.
Project이름은 Todo + Objc로 TodObjc로 지어봤다.
Interface는 Storyboard, Language는 Objective-C로 설정하고 프로젝트를 생성한다.
Objc를 써보고 익숙해지는 것이 메인 목표이니 디자인 패턴 없이 ViewController에 로직 몰아넣고 해보려고 한다.
@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를 구현해준다.
#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를 만든다.
- (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를 추가할 수 있게 했다.
- (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의 값을 반대로 바꾸게 해서 완료 여부를 수정할 수 있다.
- (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로 된 레포 몇개 열어봤을 때 읽혀졌으니 나름 목적은 달성한듯 하다. 그래도 조만간 정리를 해놔야겠다..
이야..