7 minute read

  • 프로젝트를 처음 생성하면 프로젝트 설정의 General설정창을 볼 수 있음
    • 주요 항목
      • Bundle Identifier : 안드로이드의 패키지명
      • Main Interface : 앱 실행시 처음 사용할 스토리보드
      • Device Orientation : 앱을 사용할 가로/세로 환경 지원여부
      • 앱 아이콘 : 라운드 처리를 하지 말 것. 해상도 별로 준비 필요
      • 런처이미지 : Launcher Images Source(복잡한 이미지 표현에 유리), Launch Screen source(해상도 대응에 유리)
    • 이미지 리소스는 해상도 별로 3가지를 준비하면 됨. 각 이미지는 같은 이름으로 만들고 @뒤에 해상도를 붙이면 같은 리소스로 인식 ex) image.png, image@2x.png, image@3x.png
  • 프로젝트 기본 구성
    • AppDelegate : 앱 전체의 생명주기관리를 위임받은 객체. 앱이 시작되면 가장 먼저 이 파일의 application메소드가 실행된다.

    • ViewController : 화면의 관리를 위한 컨트롤러 객체, 화면의 갯수만큼 있다. 기본적으로는 하나의 화면에 하나의 뷰 컨트롤러. 뷰의 계층을 관리한다.
      1. NavigationViewContoller : 앱의 화면이동에 대한 관리를 담당. 독립적으로 사용되지는 않음. 내부에 다른 ViewController를 포함. 상단에 네비게이션 바가 생김.
      2. TableViewController : 리스트형식의 테이블 뷰를 포함.
      3. TabBarController : 다수의 탭을 이용해 다수의 화면을 관리. 하단에 탭바가 생김.
      4. SplitViewController : Master-Detail방식의 화면을 관리.
    • .storyboard : Android의 xml레이아웃과 같이 UI를 정의. 정의하는 화면을 인터페이스 빌더라고 함.
      • 한 화면에 하나씩인 안드로이드와 달리 서로 연결되는 여러 화면이 하나의 파일로 구성되며 그 플로우를 알 수 있다. 각 화면을 Scene이라고 표현한다.
      • 커맨드+시프트+L로 오브젝트 라이브러리를 열어 뷰 컨트롤러에 오브젝트를 추가할 수 있다.
      • 하단 View as항목에서 인터페이스 빌더의 기기를 설정할 수 있다.
      • 인스펙터 창에서 각 뷰들의 상세한 설정이 가능. 커넥션, 아이덴티티, 사이즈, 속성 인스펙터
      • 실행 단축키 : 커맨드 + R
      • 새 화면을 제작하기 위해 오브젝트 라이브러리에서 View Controller를 선택해 추가한다.
      • 페이지 이동의 트리거가 될 버튼을 추가된 뷰 컨트롤러에 컨트롤+드래그하면 화면 전환을 정의할 수 있다. 이 방식을 세그웨이를 이용한 화면전환이라고 한다.
    • 앱이 실행되는 과정
      1. main()함수 실행. 이 파일은 확인이 불가하다.
      2. main함수에서 UIApplicationMain()함수를 호출(@UIApplicationMain).
      3. UIApplicationMain()에서 앱의 본체에 해당하는 UIApplication객체를 생성.
      4. UIApplication객체는 Info.plist파일을 바탕으로 데이터와 객체, UI를 로드.
      5. AppDelegate객체를 생성하고 UIApplication객체와 연결
      6. 이벤트 루프를 만드는 등 실행에 필요한 준비를 진행
      7. 실행 완료 직전 AppDelegate의 application메소드를 호출.
    • 스위프트에서는 1~5의 과정은 @UIApplicationMain으로 대체함. 시스템은 이 어노테이션이 표시된 클래스를 델리게이트 클래스로 지정함.

    • UIApplication대신 커스텀 할 수 있도록 AppDelegate가 오픈되어 있음. 앱과 생명주기를 함께 하며 시스템에서 하나의 인스턴스만 존재하도록 보장되어 있음.
  • Application의 생명주기 1 Not running : 실행되지 않음. 2 Inactive : 포그라운드, 이벤트를 받지 않고 있음. 3 Active : 포그라운드, 이벤트를 받고 있음
    1. Background : 백그라운드에서 실행 중.
    2. Suspended : 메모리에 유지되고는 있지만 실행중인 코드는 없음.
  • 생명주기 콜백 메소드
    • application(:willFinishLaunchingWithOptions) : 앱 초기화 과정 전에 호출
    • application(:didFinishlaunchingWithoptions) : 앱 초기화 과정후 표시되기 직전에 호출 커스터마이징 초기화를 여기서 할 수 있음.
    • applicationDidBecomeActive : 실행된 앱이 포그라운드에 표시될 때 호출
    • applicationWillResignactivy : active -> inactive로 바뀔 때 호출
    • applicationDidEnterBackground : 앱이 백그라운드로 진입했을 때 호출
    • applicationWillEnterForground : 앱이 백그라운드에서 포그라운드로 돌아왔을 때 호출
    • applicationWilTerminate : 앱이 종료될 때 호출
  • 앱의 인터페이스와 구성요소
    • Window > Tab bar View > Navigation View > Custom View 순서로 올라간 후 모두 합쳐져 스크린에 표시 됨.
    • UIScreen : 기기의 물리적인 화면을 정의하는 객체
    • UIWindow : 화면 그리기 지원 도구를 제공하는 객체
    • UIView : 실제로 그리기를 수행할 객체. Window와 View는 ViewController를 통해 연결된다. Window객체는 항상 root ViewController만을 참조한다.
  • 보조에디터를 이용해 클래스 파일 연결하기.
    • 인터페이스 빌더에서 뷰 컨트롤러를 활성화 한 상태로 툴바의 Editor > Assistant를 열면 보조 에디터를 열 수 있다.
    • 안드로이드에서 소스와 레이아웃을 객체의 id로 연결하는 반면 IOS에서는 직접 연결하는 방법을 많이 사용한다.
    • 인터페이스 빌더에서 뷰를 선택, 뷰 컨트롤러 소스파일에 컨트롤+드래드 하면 소스에 바로 연결 가능하다. 이때 이름과 Action/Outlet/Outlet Collection여부 등을 선택해 준다. Outlet이면 뷰의 객체가 @IBOutlet이 붙어 정해진 이름의 참조객체가 되고 Action이면 뷰가 클릭을 받았을 때의 콜백 메소드가 @IBAction과 정해준 이름이 붙어 만들어진다. 또는 위 내용의 소스를 미리 써 놓고 왼쪽에 생기는 동그라미를 드래그 해 인터페이스 빌더의 뷰와 연결할 수도 있다. 이렇게 연결된 정보는 뷰를 클릭했을 때 인스펙터 창에서 찾을 수 있다.
  • ViewController : 안드로이드가 화면단위로써 액티비티를 사용하는 것 처럼 IOS에서는 이 것을 화면단위로 사용. 가장 기본이 되는 컨트롤러이다. Navigation Controller, Tab Bar Controller등의 컨트롤러가 존재.
    • ViewController는 UIkit프레임워크(화면 구성에 필요한 UI객체들을 가지고 있다)를 import한다.
    • UIViewController 클래스를 상속해야 한다.
    • viewDidLoad() : 뷰의 로딩이 완료되었을 때 호출되는 콜백.
    • ViewController의 생명주기
      • Disappeared > Appearing > Appeared > Disappearing > Disappeared의 주기를 가진다.
        1. Disappeared : 뷰 컨트롤러가 완전히 퇴장.
        2. Appearing : 뷰 컨트롤러가 등장하는 중.
        3. Appeared : 뷰 컨트롤러가 스크린에 완전히 등장.
        4. Disappearing : 뷰 컨트롤러가 퇴장하는 중.
      • Appearing, Disappearing을 기준으로 앞 뒤에 viewWillAppear, viewDidappear의 콜백메소드가 호출된다.
      • Appearing과 Dissapearing단계는 서로 직접적으로 연결될 수 있다.
  • 로깅은 print와 NSLog 두가지를 사용할 수 있음. print는 빠르게 자료형을 포함한 메시지만, NSLog는 시간을 포함한 부가정보를 출력하며 Device Console에도 출력된다.

  • IOS앱은 UIKit프레임워크를 이용해서 구현함. import UIKit. 이 프레임워크를 포함한 앱을 만드는데 필요한 프레임워크는 모두 코코아 터치 프레임워크를 통해 구현되어 있음. 그 중 UIKit(유저 인터페이스를 제공, 접두어UI), Foundation(앱의 핵심 객체, 기본적인 데이터 형식 등 기반기술 제공, 접두어NS)은 필수요소.

  • IOS 프레임워크의 계층구조 Hardware - core OS - core Service(Foundation Framework가 여기 포함)
    • Media - Cocoa Touch - Application
  • 스플래시 화면 : 프로젝트 설정 - App Icons and Launch Images - Launch Screen File에 설정된 storyboard파일이 스플래시 화면이 된다.
    • 스플래시 화면 표시 - AppDelegate클래스의 application(:did…)메소드 호출 - 메인화면 표시 순서인 것을 이용하여 application메소드에 sleep()메소드를 사용해 메인화면 호출을 지연할 수 있다.
  • 화면 객체 제어
    • @IB~는 Interface Builder를 뜻한다. 어노테이션이 붙은 프로퍼티나 메소드는 컴파일시 인터페이스 빌더와 연결된다.
    • @IBOutlet : 화면상의 객체를 소스에서 참조하기 위해 사용. 인터페이스 빌더에서 소스상의 프로퍼티로 연결. Connection을 Outlet으로 지정.
      • 이 때 Storage를 weak으로 하면 프로퍼티가 weak타입으로 지정됨. weak타입으로 지정된 변수나 상수는 다른 곳에서 참조중이더라도 시스템이 메모리에서 제거할 수 있다. 순환 참조로 부터 벗어나는 등 메모리 관리를 위해 사용. 스토리보드의 뷰들은 strong으로 잡혀있음.
    • @IBAction : 화면상의 객체의 이벤트를 제어하기 위해 사용. IB에서 소스상의 메소드로 연결된다. Connection을 Action으로 설정하고, 대상으로 할 이벤트를 정해준다. 연결할 수 있는 이벤트 목록은 Conenction Inspector의 Send Events에서 확인 가능.
  • 인터페이스 빌더 객체와 클래스 연결 방법
    1. 인터페이스에서 객체를 우클릭하여 클래스로 드래그
    2. Conenction Inspector의 Referencing Outlets의 New Referencing Outlet 옆에 원을 클래스로 드래그
    3. 클래스에 아웃렛 프로퍼티, 메소드를 정의해 두고 옆에 원을 인터페이스 빌더의 대상 객체로 드래그
    4. 클래스에 아웃렛 프로퍼티, 메소드를 정의해 두고 ViewController의 커넥션 인스펙터에서 대상 객체, 클래스를 인터페이스 빌더로 드래그
    5. 인터페이스 빌더의 문서개요창에 있는 객체를 클래스로 드래그
  • 화면 전환 방식 : IOS에서 화면 전환은 기존의 뷰 컨트롤러에서 새 뷰 컨트롤러를 참조해 앞에 내세워주는 방식으로 전개됨.
    1. 하나의 뷰 컨트롤러에 둘 이상의 루트뷰를 갖게해서 서로 바꿔치기함. 뷰 컨트롤러와 루트뷰의 1:1 대응원칙에 어긋나므로 비추.
    2. 뷰 컨트롤러를 직접 호출(present방식) : presentation chain에 ViewController가 차례로 저장됨.
      • UIViewController에 정의되어 있는 present(_:animated:)를 호출함.
      • VC1에서 VC2를 present방식으로 호출하면 VC1은 VC2를 presentedViewController로, 그 반대는 presentingViewController로 참조할 수 있다.
      • 이전화면으로 돌아갈 때는 dismiss(animated:)메소드를 사용한다. 단 화면 종료는 스스로가 아니라 부모 뷰 컨트롤러에서 해야 하므로 presentingViewController?.dismiss(animated:)로 부모 뷰에 요청하듯이 사용하는 것이 정석임.
        1. UIViewController를 상속한 새 ViewController객체를 정의한다.
        2. 인터페이스 빌더의 ViewController의 Identity Inspector에 해당 클래스를 정의해 준다.
        3. 새 창을 띄울 @IBAction메소드의 내부에서 present()를 호출한다. 이 때 새로 띄울 ViewController의 인스턴스를 넣어야 한다. 인스턴스는 다음과 같이 생성한다. let dest = self.storyboard?.instantiateViewController(withIdentifier: “secondViewController”) (storyboard가 옵셔널, UIViewController객체도 옵셔널이므로 guard문으로 감싸주는 것이 좋다.)
        4. 위 인스턴스와 애니메이션 여부를 설정하고 present()를 호출
      • storyboard파일은 여러개 사용할 수 있는데, 기본 스토리보드는 앱의 general설정의 Main Interface에 결정되어 있다. 동적으로 가져오기 위해 UIStoryboard(name:bundle:)로 생성함.
    3. 네비게이션 컨트롤러를 이용한 전환(push) : 네비게이션 컨트롤러가 뷰 컨트롤러들의 포인터를 스택으로 갖고 화면전환을 관리한다.
      • 네비게이션 바를 갖게 됨.
      • 스택에 있는 뷰들을 한번에 종료하는 것이 가능하다.
      • 백버튼과 엣지 스와이프 애니메이션이 기본.
      • 루트 뷰 컨트롤러를 시작점으로 함. 네비게이션 컨트롤러에 직접 연결됨.
      • 스택에 뷰 컨트롤러를 추가할 때 pushViewController(), 뺄 때는 popViewController()사용
      • present와 push를 이용한 화면 전환은 기본적인 애니메이션이 다르다.
    4. 세그웨이를 이용한 화면 전환 : 스토리보드에서 뷰와 뷰 컨트롤러를 연결
      • Manual Segue : 출발점이 뷰 컨트롤러 자체인 경우
        • performSegue(withIdentifier:sender:)로 호출
        • 적정한 시점에서 호출해 주어야 한다. 주로 동적인 화면전환에 사용.
        • 인터페이스 빌더에서 뷰 컨트롤러의 도커 첫번째 아이콘을 우클릭 드래그로 전환할 뷰 컨트롤러에 연결
      • Action Segue : 출발점이 뷰인 경우
        • 인터페이스 빌더에서 버튼 등을 우클릭해서 뷰 컨트롤러에 드래그 하여 연결. 코드는 건들 필요가 없음.
        • 세그웨이 타입
          1. Present Modally : present와 같은 화면전환
          2. Show : push처럼 네비게이션 컨트롤러를 통한 화면 전환. 네비게이션 컨트롤러를 사용하지 않을 때는 Present Modally와 같은 방식으로 동작한다.
    • UnWind : 화면 복귀
      • dismiss/popViewController
      • Unwind Segue를 이용
        1. 이동하기 전 뷰 컨트롤러에서 @IBAction메소드를 제작해 준다. 이 때 파라메터의 타입은 UIStoryboardSegue로 한다.
          • 정확히는 이동하기 전 화면이 아니라 버튼을 눌렀을 때 돌아갈 목적지가 되는 뷰 컨트롤러를 말한다.
        2. 이동한 후의 뷰 컨트롤러의 인터페이스 빌더에서 백버튼으로 사용할 버튼을 우클릭 드래그로 뷰 컨트롤러 도커의 Exit아이콘에 넣는다.
    • 커스텀 세그웨이 : 세그웨이를 커스텀 하기 위해 UIStoryboardSegue클래스를 상속할 수 있다.
      • 해당 클래스의 perform()를 오버라이드 하여 화면전환을 구현한다. ex) let srcUVC = self.source // 전환을 시작할 UIViewController객체 let destUVC = self.destination // 목적지 객체 UIView.transition(from: srcUVC.view, to: destUVC.view, duration: 2, options: .transitionCurlDown) // 전환 옵션과 함께 전환실행
      • 인터페이스 빌더로 돌아와 버튼과 새 뷰컨트롤러를 액션 세그웨이로 연결한다. 이 때 타입은 Custom으로 하고, 세그웨이의 Attribute Inspector의 클래스명을 위에서 상속해 둔 커스텀 세그웨이 파일로 한다.
    • 어떠한 방식의 세그웨이던간에 한 뷰 컨트롤러에서 출발하는 다수의 세그웨이는 모두 하나의 prepare()메소드를 거치게 된다. 출발지 UIViewController에서 이 메소드를 오버라이드 해 필요한 전처리 작업을 해 줄 수 있다.
  • 다른 뷰 컨트롤러와 데이터 주고 받기
    1. 직접 값 전달하기(present, push 이동시)
      1. 이동 전 뷰컨트롤러에서 이동 후의 뷰컨트롤러의 참조를 가져온다. 멤버에 접근하므로 형변환은 필수. ex) rvc = self.storyboard?.instantiateViewController(withIdentifier: “viewController”) as? DataViewController02
      2. rvc의 멤버변수에 값을 전달한다.
      3. rvc를 present또는 pushViewController한다.
    2. 직접 값 전달하기(매뉴얼, 액션 세그웨이 이동시)
      1. prepare()의 segue객체를 이용해 목적지 뷰컨트롤러를 참조한다. 이 때도 형변환 필수.
      2. 참조한 뷰 컨트롤러에 값을 주입한다.
      3. performSegue()
    3. 이전 화면으로 값 전달하기
      1. presentingViewController로 이전 뷰컨트롤러를 참조한다.
      2. 값을 전달한 후 dismiss
    4. AppDelegate(SingleTon)을 이용해 값 전달하기
      • AppDelegate객체가 싱글톤이고, 앱과 생명주기를 함께하는 점을 활용하여 저장소처럼 사용한다.
      • UIApplication.shared.delegate를 AppDelegate로 캐스팅하여 참조한다.
    5. UserDefault를 이용해 값 전달하기
      • 안드로이드의 SharedPreference와 같음.
      • UserDefault.standard로 참조하여 저장/로드
    • lldb : 디버깅 관련 명령 po : 변수 값 확인

Categories:

Updated: