Share
Sign In
[Swift - UIKit] NavigationItem에서 #selector로 메서드 바인딩
한결
UINavigationItem 아웃렛 위에 UIBarButtonItem을 설정하기 위해서는 다양한 방식을 사용할 수 있다. 버튼 UI기 때문에 버튼의 액션을 컨트롤 할 필요가 있다. 즉, Button에 target-action 설정이 필요하다. UIBarButtonItem 클래스 인스턴스를 코드로 생성해보면 삽입해야 하는 action 속성의 타입이 Selector 로 나오는 경우를 볼 수 있다. 이 경우에 @objc 라고하는 어트리뷰트를 붙인 메서드를 등록하게 된다.
어트리뷰트 이름에서 유추할 수 있듯이 해당 속성은 Objective-C Structure에 등록된 구조체 타입이다. Objective-C에서 동적인 무언가를 만들어내는 메서드를 바인딩 할 때 사용되었던 구조체다.
Objective-의 경우런타임단에서 메서드를 바인딩하여 동적인 처리를 할 수 있게 해주는데, Swift에서는 컴파일 단계에서 메서드를 바인딩하기 때문에 Swift에서 Selector 타입을 사용하기 위해서 @objc 라고 하는 어트리뷰트가 필요해진 것이라고 보면 되겠다. (나는 그렇게 이해했다.)
정리하자면,
Swift에서 Objective-C에 의존적인 API를 활용하기 위해서 @objc 라고 하는 어트리뷰트를 자주 사용하게 될 수 있다. 이는 Swift 컴파일러가 해당 어트리뷰트를 이해할 수 있게 도와주는 역할을 하는 것이라고 쉽게 이해하면 되겠다.
참고한 문서 👇
Ha
/hankyeol
Subscribe
[Swift - System] Swift의 Sandbox 시스템과 UserDefaults.
App Sandbox 시스템 App Sandbox 시스템은 유저의 데이터를 보호하는 목적으로 커널 레벨에서 앱 자체의 데이터 접근을 제어할 수 있는 기술이다. (말이 좀 어렵다.) Swift는 기본적으로 C언어 - Objective-C 언어를 기반하기 때문에 다른 가상 머신 없이 바로 커널에 명령을 쏠 수 있다. 이 과정에서 앱이 동작하는데 필요한 특정 목적의 데이터(ex. 유저의 개인 정보라던지, 네트워크 연결성 등)를 위험에서 보호한다. 위험은 다양할 수 있는데, 앱 규모가 커질수록 더 많은 위험에 노출될 수 있겠다. 샌드박스에 보관하는 데이터를 앱과 어떻게 상호작용 할지를 개발자단에서 컨트롤 하면서, 유저로부터 올 수 있는 문제를 사전에 컨트롤 할 수 있다. 이 데이터를 앱이 사용한다는 것을 유저에게 특정 *인지 이벤트로 인식시키고, 앱이 그 데이터만 활용한다는 명확성을 부여해야 하는 시스템이 샌드박스 시스템이다. 명시적으로 허락 받지 않은 접근은 런타임이 차단한다. *내가 이해한 인지 이벤트는 다음과 같다. 우리가 앱을 설치하고 처음 켰을 때, 런치 스크린 이후에 각종 동의를 받는 경험을 했을 것이다. 이런 데이터에 대한 접근 및 활용 동의가 샌드박스를 이용해 인앱에서 데이터를 관리할 수 있는 권한을 부여한다고 볼 수 있다. - 위치 기반 데이터 활용 동의 - 사진 데이터 접근 및 활용 동의 우리가 앱스토어에서 특정 앱을 설치하면 iOS는 해당 앱을 위한 샌드박스 영역을 생성한다. 위 이미지처럼 Bundle, Data, iCloud 를 위한 공간이 생성된다. 쉽게 생각해서 유저의 의도와는 상관없이 앱의 운영을 위해 읽기, 쓰기를 위한 문서 저장 공간(애플은 데이터 파일을 Documents라고 한다 보통)을 만드는 것이다. 외부 다른 앱이나 사용자가 접근하기 힘든 공간을 이용해서 앱의 보안을 높이는 시스템이라고 볼 수 있다. 앱을 실행하면, 앱은 iOS 전체 파일관리 시스템에서 자기자신의 샌드박스를 바라본다. 샌드박스에서 필요한 데이터를 활용한다. (읽고, 쓰고, 업데이트하고 다 한다) 앱을 종료한다. 해당 앱을 위한 샌드박스 위치를 자체적으로 변경한다. 앱을 다시 실행한다. 해당 앱을 위한 변경된 샌드박스 위치를 바라볼 수 있게 한다. 즉, 특정 앱을 위한 샌드박스가 늘 같은 위치에 있는 것이 아니다. User Defaults 샌드박스 내부에 해당 앱을 위한 user's defaults database가 생성된다. 이 데이터베이스는 문서형 NoSQL 데이터베이스처럼 데이터를 키-값 형태로 저장한다. 정해진 여러 필드가 있고, 하나의 데이터가 해당 필드의 값들을 가지는 관계형 데이터베이스 형태는 아니다. UserDefaults로 관리되는 데이터는 앱이 가동되거나 어떤 이벤트를 처리할 때, 기본적인 상태들을 관리한다. (공식 문서에 따르면 - determine an app’s default state at startup or the way it acts by default.) 핵심 사용 방식은 공식 문서의 다음 문장으로 정리될 것 같다. UserDefaults 클래스가 데이터를 바라보고 있다가 캐싱을 통해 데이터를 앱에 필요하게 세팅한다. 당연히 서비스 레이어에 민감하게 적용될 수 있는 데이터나 처리는 좋지 않다. At runtime, you use UserDefaults objects to read the defaults that your app uses from a user’s defaults database. set 메서드를 통해서 키-값 형태로 값을 저장하고, UserDefaults 클래스의 인스턴스를 생성해서 저장한 값을 키로 조회할 수 있다. Dictionary를 사용하는 방식과 뭔가 비슷하다. 저장한 값은 UserDefault의 standard 메서드를 연결하여 조회할 수 있다. standard 메서드에는 불러온 값을 어떤 타입으로 가지고 올 것인지 정의할 수 있는 메서드가 함께한다. UserDefaults에 저장한 값이 정수형이라면 integer(forKey: String) 형태의 메서드를 사용하면 되는 것이다. 아직은 iOS 기반으로 앱 개발을 막 배우는 단계라서 앱 운영을 위한 데이터 관리 체계를 이정도로 정리해본다. iCloud나 외부 API를 통한 데이터 관리, 다른 앱과의 데이터 주고받기 (ex. iOS 기본 앱인 건강 앱의 데이터를 나이키 런클럽 앱에서 활용하는 방식) 방식을 더 공부해보면 이해하는 폭이 넓어질 것 같다. 참고한 문서 👇
한결
[Swift - UIKit] UIViewController에서의 View life Cycle API
UIViewController에서 View 객체를 로드하고 (그리고) 어떤 페이지로 전환되어 그 객체가 사라지는 과정을 관리하는 시스템을 내가 학습하기로는 View Life Cycle 이라고 한다. View 객체의 생명주기를 관리하는 UIViewController 클래스의 내장 오픈 메서드(API라고 부르겠다)는 여러가지가 있지만, 대표적으로 위 이미지의 5가지가 대표적일 것 같다. viewWillAppear viewIsAppearing viewDidAppear viewWillDisappear viewDidDisappear 사실, API의 prefix에 붙은 키워드만 보더라도 View 객체가 어떤 상태일지에 따라 서로 다른 API가 동작한다는 것을 쉽게 유추해 볼 수 있을 것 같다. (will, -ing, did) 모달이나 페이지 전환에 따라 특정 View 객체가 어떤 생명 주기를 가지는지를 각 API에 print 구문으로 확인해봤다. XCode로 앱을 처음 빌드할 때. UIController의 viewDidLoad가 가장 먼저 앱을 그리는 로직을 수행한다. 그리고 나서 순서대로 willAppear → isAppearing → didAppear API가 호출된다. (prefix 만으로도 쉽게 유추가 가능하다.) 버튼 액션으로 모달 페이지가 떠오를 때. 앱 화면 하단에서 떠오른 모달 페이지가 직전 View를 가리더라도, 해당 View 객체 생명 자체를 사라지게 하지 않는다. 즉, 이전 화면을 완전히 가리지 않는다면 해당 View는 생명선을 유지한다는 뜻이다. 해당 모달을 내리더라도 willAppear, isAppearing, didAppear API가 콘솔에 전혀 찍히지 않는다. 모달 페이지에서 특정 액션을 발생시켜서 뒤에 있는 View에 어떤 화면 전환이 필요하면, 그걸 처리하는 로딩 로직을 만들어야 할 것 같다. 버튼 액션으로 페이지 자체가 전환될 때. 화면이 Push되어서 완전 새로운 화면이 이전 View를 가릴 경우, 해당 View 객체는 생명을 다한다. 순서대로 willDisAppear, didDisappear API가 호출된다. 즉, 화면이 전환될 경우는 화면이 꺼짐으로 발생하는 데이터 저장이나, 업데이트 로직이 해당 생명주기 API에서 처리되어야 할 것이다.
한결
[Swift - UIKit] Alert, ActionSheet 구현하기
들어가면서. 웹이나 모바일 앱을 사용할 때, 유저에게 특정 정보를 '확인' 받거나 유저가 한 행동에 대해서 '주의'를 주거나 어떤 이유에서든 앱 내부에서 유저에게 정보를 주고 싶을 때 보통 Alert 라고 하는 요소를 활용한다. 웹 브라우저 중앙 상단에서 팝업 되거나, 모바일 앱 중앙 영역에서 작은 박스 형태로 팝업 되는 경우가 보통이다. iOS에서 동일한 역할을 하는 Alert, ActionSheet는 UIAlertController 클래스의 인스턴스로 생성한다. 문서를 살펴보면 알겠지만, UIAlertController는 기본적으로 UIViewController를 상속받는다. Alert 요소에 반영된 버튼을 통해 유저의 특정 행동(이벤트)을 받기 때문에 당연히 Control 요소가 있다. 이 말은 @IBAction을 코드로 지정해줄 수 있다는 것이겠다. 그러면 정말 간단하게 iOS Alert를 만드는 기록을 남겨본다. Alert 만들기. UIAlertController 클래스로 우리가 만들려고 하는 Alert 인스턴스의 속성들을 지정하여 생성하면 된다. 생성한 Alert 인스턴스에 액션을 추가해준다. 액션이라고 해서 거창한 것 같지만, Alert에 '확인', '취소'와 같은 버튼을 추가하는 것이라고 생각하면 편하다. 인스턴스에 addAction 메서드를 이용해서 등록하고 싶은 액션을 연결하면 된다. UIAlertAction 클래스로 인스턴스를 생성해 인자로 넘겨주면 된다. UIAlertAction의 style 속성에는 기본적으로 .default, .cancel, .destructive 라고 하는 미리 지정된 Enum의 값이 있다. Alert 버튼으로는 보통 '확인'을 받기 때문에 특정 액션을 잘 컨트롤 하지 않겠지만, *handler 속성에 특정 액션을 주입할 수도 있다. *내가 파악한 바로는, handler 속성에는 액션 객체들의 묶음이 오는데, { key in actions } 형태로 작성해서 등록하는 여러 액션을 순환하며 순차적으로 동작하는 방식인 것 같다. 공식 문서에 보면, Alert에 대한 스타일링, 액션을 지정하고 present 메서드를 이용해서 Alert 인스턴스를 등록하라고 되어 있다. 그러면 하면 된다. After configuring the alert controller with the actions and style you want, present it using the present(_:animated:completion:) method. 위 1 ~ 3의 코드를 통해 Alert를 띄워보면 아래와 같다. 아주 가볍게 잘 동작한다. ActionSheet 도 거의 동일하다. iPhone을 사용하면, Alert와 기능은 거의 비슷한데 기기의 아래에서부터 올라오는 Bottom-Up-Sheet이 있다. 이걸 ActionSheet이라고 한다. (안드로이드에서는 Dialog라고 한다고 한다.) Alert와 동일하게 문구, 버튼을 추가할 수 있다. 형태는 개발자가 지정하기 나름이다. UIAlertController에서 preferredStyle 속성의 값을 .actionSheet으로 변경해주면 된다.
한결