앱의 생명주기 이벤트를 처기하기위해선 UIApplicationDelegate 프로토콜을 준수하는 클래스에서 이벤트에 대한 메서드를 구현해야 합니다.
앱이 시잘될 때 application(:didFinishLaunchingWithOptions:) 매써드가 호출되어 앱의 초기화와 초기 설정을 수행합니다.
앱이 활성화되면 applicationDidBecomeActive(:) 이 호출되어 UI업데이트와 사용자와의 상호작용을 처리합니다.
앱이 백그라운드로 이동할때는 applicationDidEnterBackground(:) 가 호출되며 앱이 백그라운드에서 실행되는 동안 필요한 작업들을 수행합니다.
applicationWillEnterForeground(:) 는 앱이 백그라운드에서 활성 상태로 전환되기 직전에 호출되며 화면 업데이트나 다른 초기화 작업을 수행합니다.
applicationWillTerminate(_:)는 앱이 종료될 때 호출됩니다. 이때 마지막으로 저장되지 앟ㄴ는 데이터를 저장하거나 정리하는 작업을 수행합니다.
iOS 앱의 생명주기 이벤트는 앱이 시작되고 종료되는 과정 및 앱이 활성 상태에서 백그라운드 상태로 이동하거나 백그라운드 상태에서 다시 활성 상태로 복귀하는 과정을 다룹니다. 앱의 생명주기 이벤트를 처리하려면 UIApplicationDelegate 프로토콜을 준수하는 클래스에서 이벤트에 대한 메서드를 구현해야 합니다. 아래에서 주요 생명주기 이벤트와 그에 대응하는 메서드를 설명하겠습니다:
앱 시작 (App Launch): 활성 상태 (Active State): 백그라운드 상태 (Background State): 종료 (Termination):이러한 메서드를 사용하여 앱의 상태 변화에 따라 적절한 작업을 수행할 수 있습니다. 예를 들어, 백그라운드 상태에서 데이터를 저장하거나 활성 상태로 복귀할 때 UI를 업데이트하는 작업을 처리할 수 있습니다.
또한 iOS 13부터는 SceneDelegate가 도입되어 멀티-윈도우 환경에서 앱의 생명주기 이벤트를 더 세밀하게 관리할 수 있게 되었습니다. SceneDelegate를 사용하면 앱의 여러 화면을 병렬로 다루는 데 도움이 됩니다.
앱의 생명주기 이벤트를 처리할 때 주의할 점은 백그라운드 상태에서 실행 중에 시간 제한이 있고, 메모리 경고와 같은 제한이 있을 수 있다는 것입니다. 앱이 백그라운드로 이동하거나 종료될 때 데이터를 저장하고 작업을 중단할 적절한 시점을 신중하게 처리해야 합니다.
다양한 전환 방법들이 있습니다. 먼저 UINavigationController 이용한 화면전환의 경우 스택형식으로 뷰 컨트롤러를 관리하며 이전화면으로 돌아가기 용이합니다.
UITapbarController 의 경우 탭 바를 통하여 여러 뷰컨트롤러들의 화면을 전환합니다.
Present 를 사용할 경우 모달 형식으로 뷰컨트롤러를 표시하며 현재 화면 위에 새로운 화면을 띄울때 사용됩니다.
iOS 앱에서 뷰 컨트롤러 간의 전환은 앱 내에서 다양한 화면 간의 이동을 관리하는 중요한 부분입니다. 뷰 컨트롤러 사이의 전환은 사용자 경험을 개선하고 다양한 기능을 제공하는 데 사용됩니다. 뷰 컨트롤러 간의 전환을 처리하는 방법은 다음과 같습니다:
Segue (스토리보드에서의 전환): 프로그래밍 방식으로 뷰 컨트롤러 전환: Tab Bar Controller: 다른 컨트롤러와의 연결:프로퍼티 옵저버는 Swift 프로그래밍 언어에서 제공하는 기능 중 하나로, 클래스, 구조체, 또는 열거형의 프로퍼티에 할당되는 값의 변화를 감시하고 이에 반응하는 코드를 작성하는 데 사용됩니다.
willSet 은 프로퍼티에 새로운 값이 할당되기 직전에 호출되는 프로퍼티옵저버로 프로퍼티 값이 변화할때 실행할 작업을 정의합니다.
didSet 은 변화되기 이전의 값을 oldValue 라는 프로퍼티로 제공합니다.
willSet 은 새로 변화된 값을 newValue 라는 프로퍼티로 제공합니다.
프로퍼티 옵저버(Property Observer)는 Swift 프로그래밍 언어에서 제공하는 기능 중 하나로, 클래스, 구조체, 또는 열거형의 프로퍼티에 할당되는 값의 변화를 감시하고 이에 반응하는 코드를 작성하는 데 사용됩니다. 프로퍼티 옵저버는 프로퍼티의 값이 변경되는 시점에 자동으로 호출되며, 두 가지 주요 형태가 있습니다.
willSet: willSet은 프로퍼티에 새로운 값이 할당되기 직전에 호출되는 프로퍼티 옵저버입니다. 이 시점에서 프로퍼티의 현재 값(newValue 라는 기본 매개변수 이름으로 사용 가능)과 새로 할당될 값이 제공됩니다. willSet 블록 내에서 이전 값과 새로운 값에 대한 추가 작업을 수행할 수 있습니다.
swift
Copy codevar myProperty: Int = 0 { willSet(newPropertyValue) { print("현재 값: \(myProperty)") print("새로운 값: \(newPropertyValue)") } }
didSet: didSet은 프로퍼티에 새로운 값이 할당된 직후에 호출되는 프로퍼티 옵저버입니다. 이 시점에서 프로퍼티의 이전 값(oldValue 라는 기본 매개변수 이름으로 사용 가능)과 현재 값이 제공됩니다. didSet 블록 내에서 새로운 값과 이전 값에 대한 추가 작업을 수행할 수 있습니다.
swift
Copy codevar myProperty: Int = 0 { didSet(oldPropertyValue) { print("이전 값: \(oldPropertyValue)") print("현재 값: \(myProperty)") } }
프로퍼티 옵저버의 사용 사례:frame은 뷰가 부모 뷰의 좌표 시스템 내에서 위치하고 크기를 나타내는 프로퍼티이며 UIView의 위치나 크기를 설정할 때 사용합니다.
반면에 bounds는 뷰 자체의 좌표 시스템에서 위치와 크기를 나타내며 View의 크기를 알고싶거나 View 내부의 뷰를 그랠때 사용됩니다.
먼저 Codable 프로토콜을 준수하는 Swift 구조체 또는 클래스를 정의해준 후 JSON 데이터를 가져옵니다. 그리고 JSON 데이터를 Swift 객체로 디코딩하기 위해 JSONDecoder를 사용해준 후 JSONDecoder를 통해 디코딩한 객체를 사용하면 됩니다.
Codable 프로토콜을 사용하여 JSON 데이터를 Swift 객체로 디코딩(복원)하는 과정은 다음과 같습니다:
JSON 데이터와 Swift 객체 간의 대응 관계를 정의합니다. JSON 데이터를 Swift 객체로 디코딩합니다.아래는 단계별로 설명한 방법입니다.Copy code
struct Person: Codable { var name: String var age: Int var email: String? }
위의 Person 구조체는 JSON 데이터의 "name", "age", "email" 키와 객체의 속성을 매핑할 수 있습니다. Codable 프로토콜은 Decodable과 Encodable 프로토콜을 결합한 것으로, 데이터를 디코딩하고 인코딩하는 데 사용됩니다.
2. JSON 데이터를 Swift 객체로 디코딩
이제 정의한 Swift 객체를 사용하여 JSON 데이터를 디코딩합니다. Swift에서는 JSONDecoder 클래스를 사용하여 JSON 데이터를 디코딩할 수 있습니다. 아래는 디코딩하는 예제 코드입니다:
swift
Copy code
import Foundation // JSON 데이터를 담은 Data 객체
let jsonData = """ { "name": "John Doe", "age": 30, "email": "john@example.com" } """.data(using: .utf8)! do { // JSONDecoder를 생성
let decoder = JSONDecoder() // JSON 데이터를 Swift 객체로 디코딩
let person = try decoder.decode(Person.self, from: jsonData) // 디코딩된 객체를 사용
print("Name: \(person.name)") print("Age: \(person.age)") if let email = person.email { print("Email: \(email)") } } catch { print("디코딩 오류: \(error.localizedDescription)") }
위 코드에서 Person 구조체를 사용하여 JSON 데이터를 디코딩하고, 결과 객체를 person 상수에 저장합니다. 만약 디코딩 중에 오류가 발생하면 catch 블록에서 해당 오류를 처리할 수 있습니다.
이렇게 하면 JSON 데이터를 Codable 프로토콜을 준수하는 Swift 객체로 쉽게 디코딩할 수 있습니다.
Auto Layout에서 컨테이너 뷰의 역할은 UI요소들을 간편하게 정렬하거나 배치하는데 사용됩니다. 스택 뷰는 하위 뷰를 수직 또는 수평으로 배열하고 간격을 조절할 수 있습니다. 컨테이너 뷰는 동적인 크기 조정 및 화면 회전에 대응하기 용이하며 간단한 인터페이스 구성 요소들을 모아놓았기 때문에 레이아웃 관리에 효과적입니다.
Auto Layout에서 스택 뷰(Stack View)는 화면 레이아웃을 관리하는 유용한 컨테이너 뷰 중 하나입니다. 스택 뷰는 뷰 계층 구조 내에서 여러 하위 뷰(서브뷰)를 수직 또는 수평으로 배열하는 데 사용됩니다. 스택 뷰의 역할과 사용법은 다음과 같습니다:
1. 스택 뷰의 역할:
Auto Layout에서 스택 뷰와 같은 컨테이너 뷰의 역할은 UI 요소를 간단하게 정렬 및 배치하는 데 도움을 줍니다. 스택 뷰는 하위 뷰를 수직 또는 수평으로 배열하고 간격을 조정할 수 있으며, 동적인 크기 조정 및 화면 회전에 대응하기 용이합니다. 간단한 인터페이스 구성 요소를 묶어서 레이아웃을 효과적으로 관리하고 코드를 최소화합니다.
Grand Central Dispatch는 iOS 앱에서 다중 스레딩 및 병렬 작업 처리를 위한 저수준 API입니다. GCD는 큐와 블록을 사용하여 작업을 관리하며 스레드 풀을 자동으로 관리합니다.
반면, Operation Queue는 GCD 위에 구축된 고수준 API로, 작업(Operation)을 사용하여 작업 관리 및 의존성을 관리할 수 있습니다. Operation Queue는 GCD를 내부적으로 사용하며 추가적인 기능을 제공합니다.
Operation은 Task의 실행, 정지, 대기 같은 State를 알 수 있고, 이들의 취소, 순서 지정이 가능합니다.
Operation State에는 ready, executing, finished, cancelled 상태들이 있습니다.
Grand Central Dispatch (GCD)와 Operation Queue는 다중 스레드 환경에서 작업을 관리하는 데 사용되는 두 가지 다른 메커니즘입니다. 이들 간의 주요 차이점은 다음과 같습니다:
추상화 수준: 의존성 관리: 취소 및 일시 중지: 재사용성:
* GCD: GCD는 코드에서 직접 구현되므로 더 낮은 수준의 작업을 처리할 때 유용하며 코드가 더 직접적입니다.
* Operation Queue: Operation Queue는 높은 수준의 추상화를 제공하므로 더 복잡한 작업을 관리하는 데 유용하며 코드가 더 추상적입니다.일반적으로 GCD는 간단한 비동기 작업을 처리할 때 유용하며, Operation Queue는 더 복잡하거나 의존성이 있는 작업을 처리할 때 유용합니다. 프로젝트의 요구 사항에 따라 어떤 메커니즘을 선택할지 결정할 수 있으며, 두 가지를 혼합하여 사용할 수도 있습니다.Grand Central Dispatch(GCD)는 iOS 앱에서 다중 스레딩 및 병렬 작업 처리를 위한 저수준 API입니다. GCD는 큐와 블록을 사용하여 작업을 관리하며 스레드 풀을 자동으로 관리합니다.
반면, Operation Queue는 GCD 위에 구축된 고수준 API로, 작업(Operation)을 사용하여 작업 관리 및 의존성을 관리할 수 있습니다. Operation Queue는 GCD를 내부적으로 사용하며 추가적인 기능을 제공합니다.
Operation은 Task의 실행, 정지, 대기 같은 State를 알 수 있고, 이들의 취소, 순서 지정이 가능합니다.
Operation State에는 ready, executing, finished, cancelled 상태들이 있습니다.
탈출 클로저(escaping closure)는 스위프트에서 클로저의 특성 중 하나로, 클로저가 함수 외부에서 저장되거나 다른 함수로 전달되어 나중에 호출될 수 있는 경우를 가리킵니다. 이는 비동기 작업이나 콜백 기반의 API와 같은 상황에서 주로 사용됩니다.
탈출 클로저를 이해하기 위해 몇 가지 핵심 개념을 살펴보겠습니다:
클로저의 범위(scope): 클로저는 주로 그 클로저가 정의된 함수 내에서 사용됩니다. 일반적으로 함수 내부에서 정의된 클로저는 함수 내부에서 호출되며, 함수의 실행이 완료되면 그 클로저는 사라집니다. 이를 비탈출 클로저(Non-escaping closure)라고 합니다. 탈출 클로저(Escaping Closure): 반면, 탈출 클로저는 함수 내부에서 정의되었지만 함수 외부로 "탈출"할 수 있는 클로저입니다. 이것은 클로저가 함수의 실행이 완료된 후에도 호출될 수 있다는 것을 의미합니다. 주로 비동기 작업, 콜백, 델리게이트 패턴 등에서 사용됩니다.탈출 클로저의 사용 사례:Copy code
func performAsyncTask(completion: @escaping () -> Void) { // 비동기 작업을 수행하고 완료 시 클로저를 호출 DispatchQueue.global().async { // 작업 완료 completion() } } // 함수를 호출할 때 탈출 클로저를 전달 performAsyncTask { print("비동기 작업이 완료되었습니다.") }
여기서 @escaping 키워드는 클로저 매개변수가 탈출 클로저임을 나타냅니다. 탈출 클로저를 사용할 때 주의할 점은 메모리 누수를 방지하기 위해 적절한 시점에 클로저를 적절하게 해제해야 한다는 것입니다.
구조체는 값 타입을 나타내는 데이터 유형입니다. 구조체는 객체를 만들 수 있는 사용자 정의 데이터 유형이며, 속성과 메서드를 포함할 수 있습니다. 값타입이란 구조체가 인스턴스를 복사하여 전달하거나 대입할 때 새로운 복사본을 생성한다는 것을 의미합니다. 이는 데이터를 안전하게 공유하거나 변경하지 않도록 보장하고 예기치 않은 동작을 방지하는 데 도움을 줍니다.
구조체는 클래스처럼 속성을 포함할 수 있고 구조체 내에서 메서드를 정의할 수 도 있습니다.
또 구조체는 extensions 을 사용할 수 도 있고 Codable을 준수하도록 만들 수 도 있어서 JSON 형식이 필요할 때 이용할 수 도 있습니다.
구조체는 작은 데이터 모델이나 좌표와 범위같은 간단한 값, 그리고 메서드를 포함할 때 유용하게 사용되며 클래스와는 달리 값 타입으로서 테이터의 변경이 의도하지 않은 곳에서 영향을 주는것을 방지하는데 도움이 됩니다.
Swift에서 구조체(Structures)는 값 타입(Value Type)을 나타내는 데이터 유형입니다. 구조체는 객체를 만들 수 있는 사용자 정의 데이터 유형이며, 속성과 메서드를 포함할 수 있습니다. 구조체의 주요 특징은 다음과 같습니다:
값 타입(Value Type): 구조체는 값 타입으로 처리됩니다. 이것은 구조체 인스턴스를 복사하여 전달하거나 대입할 때 새로운 복사본을 생성한다는 것을 의미합니다. 이는 데이터를 안전하게 공유하거나 변경하지 않도록 보장하고 예기치 않은 동작을 방지하는 데 도움이 됩니다. 속성(Properties): 구조체는 속성(프로퍼티)을 포함할 수 있으며, 이러한 속성은 구조체의 상태나 데이터를 나타냅니다. 메서드(Methods): 구조체는 메서드(함수)를 정의하여 특정 동작을 수행할 수 있습니다. 초기화(Initialization): 구조체는 초기화 메서드를 가질 수 있으며, 인스턴스를 생성할 때 이러한 초기화 메서드를 사용하여 속성을 초기화합니다. 확장(Extensions): 구조체에 대해 나중에 추가적인 메서드나 계산된 속성을 확장(Extensions)할 수 있습니다. Codable 프로토콜 준수: 구조체는 Codable 프로토콜을 준수하도록 만들 수 있어, JSON 형식으로 직렬화하거나 역직렬화하는 데 사용됩니다.일반적으로 구조체는 작은 데이터 모델, 좌표나 범위와 같은 간단한 값, 그리고 메서드를 포함할 때 유용합니다. 구조체는 클래스(class)와 달리 참조(reference) 타입이 아니기 때문에 데이터의 변경이 예기치 않게 다른 곳에서 영향을 주는 것을 방지하는 데 도움이 됩니다.Copy code
struct Point { var x: Double var y: Double // 초기화 메서드
init(x: Double, y: Double) { self.x = x self.y = y } // 메서드
func distanceToOrigin() -> Double { return sqrt(x * x + y * y) } } var myPoint = Point(x: 3.0, y: 4.0) let distance = myPoint.distanceToOrigin() // 5.0
위의 예시에서 Point 구조체는 x와 y 속성을 가지며, 거리 계산을 위한 distanceToOrigin 메서드를 포함합니다. 구조체의 인스턴스 myPoint는 값 타입이므로 변경 가능성이 없으며 새로운 복사본을 생성하여 값을 전달합니다.
구조체 내의 메서드에서 속성 값을 변경하려면 mutating 를 사용해야 합니다. 이 키워드는 해당 메서드가 구조체 내부에서 속성을 수정할 수 있음을 의미합니다. 구조체는 기본적으로 값 타입이기 때문에 속성을 수정하려면 명시적으로 mutating 키워드를 사용해줘야 합니다.