StoryBoard vs Code

iOS 프로젝트를 처음 그리고 초반에 진행을 할 때는 무조건 스토리보드로 UI를 작성하고 ViewController와 연동하였다.

why?

쉬우니까! 간편하니까! 내가 작성한 것이니 내가 제일 잘 아니 헷갈리지도 않으니까!

BUT!

혹시라도 2명이상과 프로젝트를 진행하게 된다면 스토리보드의 가장 큰 단점이 보인다.

  • 하나의 스토리보드로 함께 작업시에 충돌할 가능성이 진부함
  • 스토리보드를 나눠서 작업을 해도 굳이 하나의 스토리보드에 들어갈 화면들이 나눠짐 -> 이후에 다시 합쳐야 하는 불편함
  • 이후에 다시 합치는 과정에서도 Ctrl+C/V를 하더라도 다시 AutoLayout을 위한 Constraint를 지정해주는 것이 어렵다!
    • 물론 정리된 문서가 있으면 금방할 수 있다고 생각했지만, 아니었다...
    • 내가 UI Component들에 지정한 이름을 보고 이게 이거였나? 이게 이거였겠지? 하면서 헷갈리는 순간 시간이 굉장히 딜레이됐다.
    • 그래서 이후로는 UI Component들의 이름도... 어떠한 체계로 명확히 작성해야한다는 것을 꺠달았따...

TabBar

예제로 진행할 탭바 StoryBoard

목표 : 이처럼 TabBarVC를 가지고 있고 2개의 VC를 삽입하여 간단한 TabBar를 구현하는 것!!

 

class TabBarViewController: UITabBarController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let profileVC = ProfileViewController()
        let vc2 = VC2()
        
        let icon1 = UITabBarItem(title: "프로필", image: UIImage(systemName: "person.circle"), selectedImage: UIImage(systemName: "person.circle"))
        let icon2 = UITabBarItem(title: "VC2", image: UIImage(systemName: "person.circle"), selectedImage: UIImage(systemName: "person.circle"))
        
        profileVC.tabBarItem = icon1
        vc2.tabBarItem = icon2
        let vcArr = [profileVC, vc2]
        self.setViewControllers(vcArr, animated: true)
    }
        
}

 

  1. TabBarVC라는 ContainerVC에 들어갈 ProfileVC, VC2를 생성한다.
  2. 각각의 VC들이 TabBar에서 보일 Item을 만든다.
  3. 2번에 이어서 붙여준다.
  4. VC들을  TabBarVC의 VC들로 지정한다.

이과정을 진행하면 문제없이 시뮬레이터에서 실행이될 것이다.

ProfileVC
VC2

보라! 정상적으로 TabBar가 구현되었다!!

응??? 근데 뭔가 이상하다??

스토리보드에 있는 ProfileVC

스토리보드에 있는 ProfileVC에는 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ라고 적힌 Label이 있는데??

아! ProfileVC에 Outlet으로 가져오면 되겠구나!

 

class ProfileViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.label.text = "aa"
    }


}

하고 실행!

Outlet을 지정한 후의 ProfileVC

엥? 아직도 안뜨네? 거기다가

Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value 라는 에러도 나타났다.

이 에러는 타입에 !를 선언해주고 nil에 접근했을 때 나타나는 건데....

스토리보드에서 profileVC와 ProfileViewController를 연결하고 Outlet에 Label을 연결했고! 아무 문제가 없어야하는데 문제가 발생??




해결 방법

guard let profileVC = self.storyboard?.instantiateViewController(withIdentifier: "ProfileVC") else { return }

위 코드처럼 바꿔주면된다.

해석하자면

  1. self가 존재하는 스토리보드에 있는 VC들 중에 "ProfileVC"라는 ID를 가진 VC를 가져온다.

스토리보드에 UI Component들을 작업하고 그 컴포넌트들을 코드로 생성한 VC에서 사용하고 싶으면 이런 방법을 써야한다.

물론 스토리보드에 UI Component들을 넣지 않고 코드로

let label = UILabel() 로 선언한 후에

text와 constraint들을 지정해 줘도 되지만... 아직까지는 그렇게 익숙하지 않으니 이 방법도 알아보게 되었다.

View

  • 사용자와 상호작용을 할 수 있는 그림(?)이라고 생각하면 된다.
    • 당연히 그림만 가지고는 어떠한 동작이나 임무를 수행할 수 없다.
  • View가 사용자로부터 User Interation을 받으면 iOS 운영체제 커널 -> 이벤트 Queue -> VC의 순서로 이벤트가 전달된다.
    • 따라서 User와 Controller 사이에 연결을 담당하는 것이 View인 것이다.

ViewController

  • UIKit의 User Interface를 관리한다.
  • 한 개의 Application 내에는 1개 이상의 ViewController를 가지고 있다.

ViewController의 종류

  1. ViewController
    • 일반적인 VC
    • 안드로이드에서의 Activity와 비슷한 역할을 수행한다.
  2. Container ViewController
    • 다른 VC(ViewController)를 자신의 rootView에 넣는다.
    • rootView 내의 VC를 상황/조건에 따라 바꿔준다. -> 메모리 공간에서의 이점은 있겠으나, 이후의 Flow를 진행할 떄에, 예기치못한 상황이나 class 타입인 VC를 다루는 데에 포인터를 확실히 제거하지 않으면 retain Cycle이 발생할 것 같다.

TabBar

  • 화면 가장 하단에 위치하여, 모드 선택에 따라 그에 맞는 View를 보여주는 Interface이다.
  • 쉽게 페이스북, 카카오톡을 생각하면 된다

TabBarViewController

  • UIKit에 UIViewController를 상속받은 UITabBarController가 존재한다.

TabBar 구현 방법(1)

  1. StoryBoard에서 Root가 될 VC에 Tab Bar Controller 를 Embed한다
  2. Item으로 넣고 싶은 VC들을 ctrl+drag를 통해 삽입한다.TabBar 구현 방법(2)
  3. Root가 될 VC에 UITabBarController를 상속한다.
  4. 넣고 싶은 VC들을 생성하고 각각의 VC들의 tabBarItem을 초기화한다.
    • 이때, tabBarItem이란, TabBar에 보일 Item(즉, 버튼)이다
  5. 해당 VC array를 rootVC의 viewControllers에 넣는다.

VC 이동 하는 방법

  • 하단에 TabBar Item Button을 터치/클릭 하여 전환

H.I.G in Apple

  • 일반적으로 3~5개의 탭을 사용하라.
    • 너무 적으면 굳이 TabBar를 사용할 이유가 없으며, 너무 많으면 사용자에게 혼란을 줄 것이다.
  • 다른 영역으로 이동할 때, Tab Bar를 숨기지 마라

ORM

  • 객체 - 관계 매핑을 자동으로 매핑해준다.
  • 클래스와 테이블은 서로 호환이 되지 않기 떄문에, 불일치가 발생할 수 있다.
    • 이를 ORM을 통해 객체 간의 관계를 바탕으로 SQL문을 자동으로 생성하여 불일치를 해결!

결론 : ORM을 사용하면 SQL문 필요없이 객체를 통해 간접적으로 DB를 조작할 수 있다.


장점

  • 객체지향적인 코드
    • 클래스의 메서드를 통해 DB의 조작이 가능하기 때문에, 개발자가 프로그래밍(비즈니스 로직)에만 집중할 수 있다.
    • 객체에 대한 코드를 별도로 작성하여 가독성을 높일 수 있다.
  • 재사용, 유지보수 성 용이
    • 객체로 작성되어있기 떄문에 재활용이 가능하다.
  • DBMS에 대한 종속성 하락
    • 객체 간의 관계를 바탕으로 SQL을 생성하기 때문에, RDBMS의 데이터 구조와 객체지향 모뎅 사이의 간격을 좁힐 수 있다.

iOS Local DB 비교

Why?

  • iOS 프로젝트를 진행함에 있어서 서버 유지 비용이 많이 듬 -> 즉, 서버를 지속적으로 유지하기가 힘듬
  • 최대한 Local DB를 이용해서 비용을 줄이고 최대한 iOS 프레임워크를 잘 사용한 서비스를 구현하자!!

1. SQLite

  • 가장 많이 사용되는 오픈소스 기반의 DB
  • SQL 구현 가능
  • 가장 널리 사용되어 있어, 참고 자료가 많다.

특징

  • 서버로부터의 독립성
  • 설정이 쉬움
  • 여러 프로세스/쓰레드에서도 안전하게 접근 가능 -> 이후에 Realm
  • Write 트랙잭션 시에, Lock의 단위가 Table이 아닌 DB자체에 Lock을 건다
  • Date Time 과 같은 Field가 존재하지 않음. (날짜 단위로 저장 시는 문자열로 잘 파싱하면 문제 없겠지만, 시간 단위까지 내려간다면 신경 쓸게 많아서 번거로울 것 같다.)

자세히

  • API는 라이브러리를 호출하는 것만 있으며, 데이터를 저장하는 데에 하나의 파일만을 사용한다.

2. Core Data

  • 객체에 중점을 둠

특징

  • 상대적으로 많은 저장공간, 메모리 사용
  • 속도가 빠르다
  • In- Memory 방식
    • 메모리에 로딩된 객체들에 대해서만 수정이 가능하다.
  • Thread-Safe하지 않음

3. Realm

  • 최근 널리, 많이 유행하고 사용되고 있는 DB
  • 객체 중심의 DB
  • Android에서도 많이 사용됨
  • ORM 이 아니다 -> BackGround에서 적용되는 SQL 쿼리를 실행하지 않는다.(반대로 ORM은 간단한 업무도 상대적으로 많은 쿼리문을 실행한다는 말)
    • 따라서 Realm이 다른 DB보다 빠른 것인가?

특징

  • 속도가 빠르다
  • 무료
  • iOS/Android 플랫폼 간에 DB File 공유 가능
  • Realm Studio가 있어서 DB 자체를 쉽게 확인 가능.
  • Main Thread를 이용하고 있다 (이전에 하나의 프로젝트를 진행하면서 Dispatch Queue 관리를 잘 못했을 때, 항상 에러가 나서 애를 먹었다...)
  • 쿼리가 많지 않음

4. UserDefault

  • Android에서의 SharedPreference와 비슷하다.
  • 간단하게 Toggle을 위한 변수, 온보딩 유무 체크 등을 확인하기 위해 사용하면 좋을 듯

이어서 다음 포스팅에는 ORM을 알아보자!!!!

+ Recent posts