반응형
해당 글에서는 AppGroup으로 구성한 UserDefaults와 Observer 페탄을 구성하는 방법에 대해서 공유합니다.
1) UserDefalts
1. UserDefaults
💡 UserDefaults란?
- iOS에서 제공하는 데이터 저장소를 의미하며 앱 내에서 작은 데이터를 저장하고 읽어올때 사용합니다.
- Key-Value 형태로 데이터를 저장하며, 데이터 타입은 문자열, 숫자, 불리언 등 기본 데이터 타입뿐만 아니라, 배열, 딕셔너리 등의 객체도 저장할 수 있습니다.AppGroup을 통해서 동일한 개발자 계정으로 배포되는 앱끼리 데이터 공유할 수 있습니다.
[ 더 알아보기 ]
💡 DispatchQueue란?
- iOS에서 DispatchQueue는 스레드 관리를 위한 클래스 중 하나로, Grand Central Dispatch(GCD)의 핵심 요소 중 하나입니다. GCD는 멀티코어 하드웨어에서 작업을 병렬로 수행하기 위한 기능을 제공합니다.
- global() DispatchQueue는 백그라운드에서 작업을 실행하도록 지정된 DispatchQueue입니다. 이를 통해 작업이 메인 스레드에서 실행되는 것을 방지하고, 앱의 반응성을 향상시킬 수 있습니다.
[참고] 다른 저장소에 대해 확인을 해보고 싶으시면 아래의 글을 참고하시면 도움이 됩니다.
2. UserDefaults 메서드
메서드 | 분류 | 설명 |
UserDefaults(suiteName: "AppGroup") | 객체 구성 | - iOS에서 제공하는 데이터 저장소인 UserDefaults를 App Group을 통해 공유하기 위한 메서드입니다. |
UserDefaults.standard.set(value, forKey: "key") | 객체의 값 구성 | - UserDefaults에 저장된 키값에 따라 값을 반환합니다. - 반환된 값은 Any? 타입으로, 성공적으로 값을 가져오지 못했을 경우 nil을 반환합니다. value(forKey:) 메서드를 호출하기 전에 UserDefaults.standard 객체에 값을 저장하고 있어야 합니다. |
UserDefaults.value(forKey:"key") | 객체의 값 조회 | - 앱의 설정 정보를 저장하는 데 사용되며, 앱에서 사용자의 기본 설정을 유지하려는 경우 유용합니다. - addObserver() 메서드를 사용하여 UserDefaults의 변경 사항을 감지하고 이에 대한 알림을 받을 수 있습니다. |
// UserDefaults(suiteName: "AppGroup")
var sharedUserDefaults: UserDefaults = UserDefaults(suiteName: "group.xxx.appgroup")!
// UserDefaults.standard.set(value, forKey: "key")
sharedUserDefaults.set("John Doe", forKey: "username")
// UserDefaults.value(forKey:"key")
sharedUserDefaults.value(forKey: "username") as? Data
3. UserDefaults의 저장 가능 데이터 타입
데이터 타입 | 설명 |
Bool | 불리언 값, true 또는 false |
Int | 정수 값 |
Float | 부동소수점 값 |
Double | 더블 값, 더 정확한 부동소수점 값 |
Data | 바이너리 데이터 |
String | 문자열 |
URL | URL 링크 값 |
Array | 배열 |
Dictionary | 딕셔너리 |
2) 옵저버 패턴(Observer Pattern)
💡 옵저버 패턴(Observer pattern) 이란?
- 파일 생성, 수정, 삭제 등 파일 관리에서 발생하는 이벤트를 감시하는 데 사용되며 관찰 대상 객체와 이를 감시하는 옵저버 객체로 구성됩니다.
- 관찰 대상 객체는 변경 사항이 있을 때마다 옵저버 객체들에게 이를 알리며, 각각의 옵저버 객체는 이벤트에 따라 특정 작업을 수행합니다.
- 예를 들어 파일이 생성될 때마다 자동 백업 기능을 구현하거나, 파일이 수정될 때마다 특정 프로그램으로 열 수 있는 기능을 구현할 수도 있습니다.
1. UIViewController에서 옵저버 패턴 사용
💡 UIViewController는 KVO(Key-Value Observing)를 지원하는데, 이는 객체의 특정 프로퍼티가 변경될 때 알림을 받을 수 있는 기능입니다.
- 이 기능을 이용하면 다른 객체에서 해당 뷰 컨트롤러의 프로퍼티 변경을 감지하고, 이에 따라 적절한 처리를 할 수 있습니다.
- UIViewController의 observeValue 메소드는 KVO를 사용하여 프로퍼티의 변경을 감지하는 메소드입니다. 이 메소드는 다음과 같은 형태를 갖습니다.
2. observeValue 메서드
💡override func observeValue 란?
- 메서드는 객체의 값이 변경될 때 호출되는 메서드입니다. 이 메서드는 Key-Value Observing (KVO) 패턴을 구현할 때 사용됩니다.
💡KVO(Key-Value Observing) 란?
- KVO는 객체의 속성이 변경될 때 해당 객체를 관찰하고 있는 객체에게 알리는 패턴입니다. 이 메서드는 KVO를 구현하는 과정에서 구현해야 하는 메서드 중 하나입니다.
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
super.observeValue(forKeyPath: keyPath,of: object,change: change,context: context)
}
매개 변수 | 설명 |
keyPath | 관찰할 속성의 수신기에 대한 상대적인 키 경로입니다. |
object | 관찰되는 객체입니다. |
change | 개체에 대한 keyPath의 속성 값에 대해 수행된 변경 사항을 설명하는 사전입니다. |
context | 키-값 관찰 알림을 수신하도록 등록된 때 제공된 값입니다. |
💡 observeValue 메소드를 사용할 때 주의할 점은, 해당 뷰 컨트롤러가 dealloc될 때 반드시 KVO를 해제해주어야 한다는 것입니다. 이를 해제하지 않으면 메모리 릭(leak)이 발생할 수 있습니다.
3) Extenstion과 App 간의 데이터 통신
1. Extenstion (송신부) : SampleBuffer
💡 BroadCast Extenstion으로 부터 구성한 데이터를 UserDefalts에 저장을 합니다.
1. 화면 공유를 수행하면 SampleBuffer 데이터가 반복적으로 출력이 됩니다.
2. handleVideoFrameImage() 를 호출하면 SampleBuffer를 이미지 형태의 Data 타입으로 변경합니다.
3. 변경된 Data 타입을 UserDefaults 공간에 “sampleBufferData”키 값으로 저장합니다.
/**
* 방송 시작이 되고 실시간으로 화면공유 데이터를 전송합니다.
*/
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType{
// [CASE1] 비디오 처리
case RPSampleBufferType.video:
// SampleBuffer 데이터를 이미지용 Data로 변환합니다.
self.handleVideoFrameImage(sampleBuffer: sampleBuffer)
// [CASE2] 오디오 앱 처리
case RPSampleBufferType.audioApp:
break
// [CASE3] 오디오 마이크 처리
case RPSampleBufferType.audioMic:
break
@unknown default:
fatalError("")
}
}
/**
* CMSampleBuffer 데이터를 이미지로 변환하여 실시간 UserDefaults 저장소에 저장하는 함수
*/
func handleVideoFrameImage(sampleBuffer: CMSampleBuffer) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let ciimage = CIImage(cvPixelBuffer: imageBuffer)
let context = CIContext(options: nil)
let cgImage = context.createCGImage(ciimage, from: ciimage.extent)!
let image = UIImage(cgImage: cgImage)
let imageData = UIImage.pngData(image)()
DispatchQueue.global().async {
self.sharedUserDefaults.set(imageData, forKey: "sampleBufferData") // data 타입 형태로 UserDefaults에 저장합니다.
self.sharedUserDefaults.synchronize()
}
}
2. App(수신부) : ViewController
1. App viewDidLoad()
💡 앱의 뷰가 출력되는 타임에 UserDefaults의 옵저버를 등록합니다.
override func viewDidLoad() {
super.viewDidLoad()
sharedUserDefaults.addObserver(self, forKeyPath: "sampleBufferData", options: [.initial, .new], context: nil)
}
2. App observeValue()
💡 옵저버에 등록한 키 값을 기반으로 변경이 발생하면 observeValue() 메서드가 수행이 됩니다.
- 해당 메서드는 키의 값이 변경되는 경우 수행되도록 구성하였습니다.
- 그리고 전달 받은 값은 object 형태로 전달을 받는데 이를 Data 타입으로 변형하고 다시 이미지로 변경하여 최종 전달받은 값에 대해서 이미지에 출력을 합니다.
/**
* [Lifecycle] 옵저버에서 처리한 값을 반환합니다.
*/
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath = keyPath, let change = change else { return }
// [CASE1] UserDefaults의 키 값이 "sampleBufferData" 인 경우
if keyPath == "sampleBufferData" {
// [STEP1] 해당 키의 값이 변경된 경우 수행됩니다.
if let newValue = change[.newKey] {
// [STEP2] 반환되는 값을 데이터 타입으로 파싱합니다.
let data: Data = newValue as! Data
print("New value: \\(data)")
// [STEP3] 데이터를 이미지 타입의 데이터로 변경합니다.
let image = UIImage(data: data)
// [STEP4] view에 이미지를 출력합니다.
imageView.image = image
}
}
// [CASE2] 이외의 경우
else {
return;
}
}
오늘도 감사합니다. 😀
반응형
'Swift > 이해하기' 카테고리의 다른 글
[Swift] UIViewController 라이프사이클 이해하기 (0) | 2023.05.09 |
---|---|
[Swift] 저장소 이해하기 : NotificationCenter, UserDefaults, AppGroup(FileManager) (0) | 2023.05.04 |
[Swift] iOS 앱 상태 이해 및 백그라운드로 이동방법 : 앱 라이프 사이클, 앱 벗어나기 (1) | 2023.04.25 |
[Swift] 화면 공유 기술 - 3 : 전체 시스템 화면 공유 개발 (3) | 2023.03.10 |
[Swift] 화면 공유 기술 - 2 : 전체 시스템 화면 공유 구축 (0) | 2023.03.10 |