IOS 기본 - 1
- 프로젝트를 처음 생성하면 프로젝트 설정의 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 : 화면의 관리를 위한 컨트롤러 객체, 화면의 갯수만큼 있다.
기본적으로는 하나의 화면에 하나의 뷰 컨트롤러. 뷰의 계층을 관리한다.
- NavigationViewContoller : 앱의 화면이동에 대한 관리를 담당. 독립적으로 사용되지는 않음. 내부에 다른 ViewController를 포함. 상단에 네비게이션 바가 생김.
- TableViewController : 리스트형식의 테이블 뷰를 포함.
- TabBarController : 다수의 탭을 이용해 다수의 화면을 관리. 하단에 탭바가 생김.
- SplitViewController : Master-Detail방식의 화면을 관리.
- .storyboard : Android의 xml레이아웃과 같이 UI를 정의. 정의하는 화면을 인터페이스 빌더라고 함.
- 한 화면에 하나씩인 안드로이드와 달리 서로 연결되는 여러 화면이 하나의 파일로 구성되며 그 플로우를 알 수 있다. 각 화면을 Scene이라고 표현한다.
- 커맨드+시프트+L로 오브젝트 라이브러리를 열어 뷰 컨트롤러에 오브젝트를 추가할 수 있다.
- 하단 View as항목에서 인터페이스 빌더의 기기를 설정할 수 있다.
- 인스펙터 창에서 각 뷰들의 상세한 설정이 가능. 커넥션, 아이덴티티, 사이즈, 속성 인스펙터
- 실행 단축키 : 커맨드 + R
- 새 화면을 제작하기 위해 오브젝트 라이브러리에서 View Controller를 선택해 추가한다.
- 페이지 이동의 트리거가 될 버튼을 추가된 뷰 컨트롤러에 컨트롤+드래그하면 화면 전환을 정의할 수 있다. 이 방식을 세그웨이를 이용한 화면전환이라고 한다.
- 앱이 실행되는 과정
- main()함수 실행. 이 파일은 확인이 불가하다.
- main함수에서 UIApplicationMain()함수를 호출(@UIApplicationMain).
- UIApplicationMain()에서 앱의 본체에 해당하는 UIApplication객체를 생성.
- UIApplication객체는 Info.plist파일을 바탕으로 데이터와 객체, UI를 로드.
- AppDelegate객체를 생성하고 UIApplication객체와 연결
- 이벤트 루프를 만드는 등 실행에 필요한 준비를 진행
- 실행 완료 직전 AppDelegate의 application메소드를 호출.
-
스위프트에서는 1~5의 과정은 @UIApplicationMain으로 대체함. 시스템은 이 어노테이션이 표시된 클래스를 델리게이트 클래스로 지정함.
- UIApplication대신 커스텀 할 수 있도록 AppDelegate가 오픈되어 있음. 앱과 생명주기를 함께 하며 시스템에서 하나의 인스턴스만 존재하도록 보장되어 있음.
-
- Application의 생명주기
1 Not running : 실행되지 않음.
2 Inactive : 포그라운드, 이벤트를 받지 않고 있음.
3 Active : 포그라운드, 이벤트를 받고 있음
- Background : 백그라운드에서 실행 중.
- 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의 주기를 가진다.
- Disappeared : 뷰 컨트롤러가 완전히 퇴장.
- Appearing : 뷰 컨트롤러가 등장하는 중.
- Appeared : 뷰 컨트롤러가 스크린에 완전히 등장.
- Disappearing : 뷰 컨트롤러가 퇴장하는 중.
- Appearing, Disappearing을 기준으로 앞 뒤에 viewWillAppear, viewDidappear의 콜백메소드가 호출된다.
- Appearing과 Dissapearing단계는 서로 직접적으로 연결될 수 있다.
- Disappeared > Appearing > Appeared > Disappearing > Disappeared의 주기를 가진다.
-
로깅은 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에서 확인 가능.
- 인터페이스 빌더 객체와 클래스 연결 방법
- 인터페이스에서 객체를 우클릭하여 클래스로 드래그
- Conenction Inspector의 Referencing Outlets의 New Referencing Outlet 옆에 원을 클래스로 드래그
- 클래스에 아웃렛 프로퍼티, 메소드를 정의해 두고 옆에 원을 인터페이스 빌더의 대상 객체로 드래그
- 클래스에 아웃렛 프로퍼티, 메소드를 정의해 두고 ViewController의 커넥션 인스펙터에서 대상 객체, 클래스를 인터페이스 빌더로 드래그
- 인터페이스 빌더의 문서개요창에 있는 객체를 클래스로 드래그
- 화면 전환 방식 : IOS에서 화면 전환은 기존의 뷰 컨트롤러에서 새 뷰 컨트롤러를 참조해 앞에 내세워주는 방식으로 전개됨.
- 하나의 뷰 컨트롤러에 둘 이상의 루트뷰를 갖게해서 서로 바꿔치기함. 뷰 컨트롤러와 루트뷰의 1:1 대응원칙에 어긋나므로 비추.
- 뷰 컨트롤러를 직접 호출(present방식) : presentation chain에 ViewController가 차례로 저장됨.
- UIViewController에 정의되어 있는 present(_:animated:)를 호출함.
- VC1에서 VC2를 present방식으로 호출하면 VC1은 VC2를 presentedViewController로, 그 반대는 presentingViewController로 참조할 수 있다.
- 이전화면으로 돌아갈 때는 dismiss(animated:)메소드를 사용한다. 단 화면 종료는 스스로가 아니라 부모 뷰 컨트롤러에서 해야 하므로
presentingViewController?.dismiss(animated:)로 부모 뷰에 요청하듯이 사용하는 것이 정석임.
- UIViewController를 상속한 새 ViewController객체를 정의한다.
- 인터페이스 빌더의 ViewController의 Identity Inspector에 해당 클래스를 정의해 준다.
- 새 창을 띄울 @IBAction메소드의 내부에서 present()를 호출한다. 이 때 새로 띄울 ViewController의 인스턴스를 넣어야 한다. 인스턴스는 다음과 같이 생성한다. let dest = self.storyboard?.instantiateViewController(withIdentifier: “secondViewController”) (storyboard가 옵셔널, UIViewController객체도 옵셔널이므로 guard문으로 감싸주는 것이 좋다.)
- 위 인스턴스와 애니메이션 여부를 설정하고 present()를 호출
- storyboard파일은 여러개 사용할 수 있는데, 기본 스토리보드는 앱의 general설정의 Main Interface에 결정되어 있다. 동적으로 가져오기 위해 UIStoryboard(name:bundle:)로 생성함.
- 네비게이션 컨트롤러를 이용한 전환(push) : 네비게이션 컨트롤러가 뷰 컨트롤러들의 포인터를 스택으로 갖고 화면전환을 관리한다.
- 네비게이션 바를 갖게 됨.
- 스택에 있는 뷰들을 한번에 종료하는 것이 가능하다.
- 백버튼과 엣지 스와이프 애니메이션이 기본.
- 루트 뷰 컨트롤러를 시작점으로 함. 네비게이션 컨트롤러에 직접 연결됨.
- 스택에 뷰 컨트롤러를 추가할 때 pushViewController(), 뺄 때는 popViewController()사용
- present와 push를 이용한 화면 전환은 기본적인 애니메이션이 다르다.
- 세그웨이를 이용한 화면 전환 : 스토리보드에서 뷰와 뷰 컨트롤러를 연결
- Manual Segue : 출발점이 뷰 컨트롤러 자체인 경우
- performSegue(withIdentifier:sender:)로 호출
- 적정한 시점에서 호출해 주어야 한다. 주로 동적인 화면전환에 사용.
- 인터페이스 빌더에서 뷰 컨트롤러의 도커 첫번째 아이콘을 우클릭 드래그로 전환할 뷰 컨트롤러에 연결
- Action Segue : 출발점이 뷰인 경우
- 인터페이스 빌더에서 버튼 등을 우클릭해서 뷰 컨트롤러에 드래그 하여 연결. 코드는 건들 필요가 없음.
- 세그웨이 타입
- Present Modally : present와 같은 화면전환
- Show : push처럼 네비게이션 컨트롤러를 통한 화면 전환. 네비게이션 컨트롤러를 사용하지 않을 때는 Present Modally와 같은 방식으로 동작한다.
- Manual Segue : 출발점이 뷰 컨트롤러 자체인 경우
- UnWind : 화면 복귀
- dismiss/popViewController
- Unwind Segue를 이용
- 이동하기 전 뷰 컨트롤러에서 @IBAction메소드를 제작해 준다. 이 때 파라메터의 타입은 UIStoryboardSegue로 한다.
- 정확히는 이동하기 전 화면이 아니라 버튼을 눌렀을 때 돌아갈 목적지가 되는 뷰 컨트롤러를 말한다.
- 이동한 후의 뷰 컨트롤러의 인터페이스 빌더에서 백버튼으로 사용할 버튼을 우클릭 드래그로 뷰 컨트롤러 도커의 Exit아이콘에 넣는다.
- 이동하기 전 뷰 컨트롤러에서 @IBAction메소드를 제작해 준다. 이 때 파라메터의 타입은 UIStoryboardSegue로 한다.
- 커스텀 세그웨이 : 세그웨이를 커스텀 하기 위해 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에서 이 메소드를 오버라이드 해 필요한 전처리 작업을 해 줄 수 있다.
- 다른 뷰 컨트롤러와 데이터 주고 받기
- 직접 값 전달하기(present, push 이동시)
- 이동 전 뷰컨트롤러에서 이동 후의 뷰컨트롤러의 참조를 가져온다. 멤버에 접근하므로 형변환은 필수. ex) rvc = self.storyboard?.instantiateViewController(withIdentifier: “viewController”) as? DataViewController02
- rvc의 멤버변수에 값을 전달한다.
- rvc를 present또는 pushViewController한다.
- 직접 값 전달하기(매뉴얼, 액션 세그웨이 이동시)
- prepare()의 segue객체를 이용해 목적지 뷰컨트롤러를 참조한다. 이 때도 형변환 필수.
- 참조한 뷰 컨트롤러에 값을 주입한다.
- performSegue()
- 이전 화면으로 값 전달하기
- presentingViewController로 이전 뷰컨트롤러를 참조한다.
- 값을 전달한 후 dismiss
- AppDelegate(SingleTon)을 이용해 값 전달하기
- AppDelegate객체가 싱글톤이고, 앱과 생명주기를 함께하는 점을 활용하여 저장소처럼 사용한다.
- UIApplication.shared.delegate를 AppDelegate로 캐스팅하여 참조한다.
- UserDefault를 이용해 값 전달하기
- 안드로이드의 SharedPreference와 같음.
- UserDefault.standard로 참조하여 저장/로드
- lldb : 디버깅 관련 명령 po : 변수 값 확인
- 직접 값 전달하기(present, push 이동시)