์ง๋ ๊ธ์ ์ด์ด ์ด๋ฒ์๋ DeviceActivity๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง์ ๋ํ ๊ธ์ด๋ค.
๋ค์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์๋ค !
https://developer.apple.com/documentation/DeviceActivity
DeviceActivity | Apple Developer Documentation
Monitor device activity with your app extension while maintaining user privacy.
developer.apple.com
์ด๋ฒ ๊ธ์ ๋ด๊ฐ ์งํ ์ค์ธ ํ๋ก์ ํธ์์ ์๋นํ ์ค์ํ ์ฃผ๊ธฐ๋ฅ์ ๊ผญ ํ์ํ framework์ด๋ฏ๋ก, ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐ๋ผํ๋ฉด์ ํด๋ณด๋ ค๊ณ ํ๋ค.
๊ทธ ์ ์, ์ด framework๋ ์ฑ ํ์ฅ ๊ธฐ๋ฅ์ ์ฌ์ฉํด ์ฌ์ฉ์์ ํ๋ผ์ด๋ฒ์๋ฅผ ์ ์งํ๋ฉด์, ๊ธฐ๊ธฐ ํ๋์ ๋ชจ๋ํฐ๋ง ํ๋ค.
์ด์ ๊ธ๊ณผ ์กฐ๊ธ ๊ฒน์น๋ ๋ถ๋ถ์ด ์์์ ์์ง๋ง,
1. ํน์ ์๊ฐ๋์ ํ๋์ ๋ชจ๋ํฐ๋ง ํ ์ ์๋ค.
2. ํ๋์ด ๋ฏธ๋ฆฌ ์ค์ ๋ ํ๊ณ์ ๋๋ฌํ ๋ ๊ฒฝ๊ณ ๋ฅผ ์ค ์ ์๋ค.
3. ์ฑ๊ณผ ์น์ฌ์ดํธ์์ ์ฌ์ฉ๋ ์๊ฐ์ ๋ชจ๋ํฐ๋ง ํ๋ค.
์ด์ ๊ฐ๊ฐ์ Topic์ ํ๋์ฉ ๋ค๋ค๋ณด์ !
Manage Activities
- struct DeviceActivityEvent
- ์ ํ๋ฆฌ์ผ์ด์ , ์นดํ ๊ณ ๋ฆฌ ๋๋ ์น์ฌ์ดํธ ํ๋์ ๋ํ๋ด๋ ์ด๋ฒคํธ
- struct DeviceActivityName
- ํ๋์ ๊ณ ์ ํ ์ด๋ฆ์ ๋ํ๋ธ๋ค.
- struct DeviceActivitySchedule
- ๊ธฐ๊ธฐ ํ๋์ ๋ชจ๋ํฐ๋งํ ๋์ ์ผ์ ๊ธฐ๋ฐ ์ค์ผ์ค์ ๋ํ๋ธ๋ค.
- struct DeviceActivityCenter
- ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ฅ์ด ์ผ์ ์ ๋ฐ๋ผ ๊ธฐ๊ธฐ ํ๋ ๋ชจ๋ํฐ๋ง์ ์์ํ ์ ์๋๋ก ํ๋ ํด๋์ค
Monitor Activity
- class DeviceActivityMonitor
- ์ผ์ ์ ๋ฐ๋ผ ๊ธฐ๊ธฐ ํ๋์ ๋ชจ๋ํฐ๋งํ๋ ๊ฐ์ฒด
Errors
- enum MonitoringError
- ํ๋ ๋ชจ๋ํฐ๋ง์ ์์ํ ๋ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๋ค์ ๋์ดํ๋ ์ด๊ฑฐํ
Classes
- class DeviceActivityAuthorization
- ๊ธฐ๊ธฐ ํ๋ ๋ชจ๋ํฐ๋ง์ ์ํ ๊ถํ ๋ถ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋ ํด๋์ค์ด๋ค.
Protocols
- protocol DeviceActivityAuthorizing
- ๊ธฐ๊ธฐ ํ๋ ๋ชจ๋ํฐ๋ง์ ๋ํ ๊ถํ ๋ถ์ฌ๋ฅผ ์ ์ํ๋ ํ๋กํ ์ฝ์ด๋ค.
- protocol DeviceActivityReportExtension
- ๊ธฐ๊ธฐ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ณ ํ๋ ์ฑ extension์ด๋ค.
- protocol DeviceActivityReportScene
- ์ฌ์ฉ์ ์ ์ ๊ธฐ๊ธฐ ํ๋ report scene์ ์ ์ํ๋ ํ๋กํ ์ฝ์ด๋ค.
Structures
- struct DeviceActivityData
- ํน์ DeviceActivityData.Device์์ DeviceActivityData.User์ ํ๋์ ๋ํ๋ธ๋ค.
- struct DeviceActivityFilter
- ๋ณด๊ณ ์์ ํฌํจํ ๊ธฐ๊ธฐ ํ๋ ๋ฐ์ดํฐ๋ฅผ ํํฐ๋งํ๋ ํ์ .
- struct DeviceActivityReport
- ์ฌ์ฉ์์ ์ ํ๋ฆฌ์ผ์ด์ , ์นดํ ๊ณ ๋ฆฌ ๋ฐ ์น ๋๋ฉ์ธ ํ๋์ ํ๋ผ์ด๋ฒ์๋ฅผ ๋ณดํธํ๋ ๋ฐฉ์์ผ๋ก ๋ณด๊ณ ํ๋ view์ด๋ค.
- struct DeviceActivityReportBuilder
- ํ๋ ์ด์์ DeviceActivityReportScenes์ ๊ฒฐํฉํ์ฌ ๋จ์ผ ์ฅ๋ฉด์ ์์ฑํ๋ ๊ฒฐ๊ณผ ๋น๋.
- struct DeviceActivityResults
- ํํฐ๋ง๋ ๊ธฐ๊ธฐ ํ๋ ๊ฒฐ๊ณผ์ ๋น๋๊ธฐ sequence.
ํ๋ก์ ํธ์ ๋ฐ์ํ๊ธฐ
์ด์ xcode์ ํ๋ก์ ํธ๋ฅผ ํ๊ณ , ํด๋น api๋ฅผ ์ฌ์ฉํด๋ณด๋ ๊ณผ์ ์ ์ ๋ฆฌํ๋ ค ํ๋ค.
๋จผ์ , ๊ด๋ จ๋ extension์ ์ค์นํด์ค๋ค.
ํ๊น์์ ํ๋จ์ + ๋ฒํผ์ ๋๋ฌ add target์ ํด์ค๋ค.
๊ทธ๋ผ, ๋ค์๊ณผ ๊ฐ์ ํ์ ์ด ๋จ๋๋ฐ, ์ด ๋ DeviceActivity Monitor Extension๊ณผ Device Activity Report Extension์ ๊ฐ๊ฐ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
์ด๋ ๊ฒ ๋ ๊ฐ์ extension์ ๋ชจ๋ ์ถ๊ฐํ๋ค๋ฉด, ์ด๋ ๊ฒ xcode์ ์ถ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด์ extension์ ์ถ๊ฐํ์์ผ๋ฉด, ๋์ ๊ฐ์ ๊ฒฝ์ฐ, ๋๋ถ๋ถ์ ์ฝ๋๋ฅผ UIKit์ผ๋ก ์งค ์์ ์ด๊ธฐ์ SwiftUI ๊ธฐ๋ฐ์ api์ UIKit์ ์๋ก ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํ๋ค.
์ฆ, ๋ ๊ฐ์ framework๋ฅผ ํผ์ฉํด์ ์ธ ์ ์๋ ํ๊ฒฝ์ ์ธํ ํด์ผ ํ๋ค.
UIKit๊ณผ SwiftUI ํผ์ฉํ๊ธฐ
UIHostingController๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ์ง๋ง, ์๋ฌด๋ฆฌ ์ฌ์ฉํด์ ์ฐ๊ฒฐ์ ํด๋, ์๊พธ ์ฌ์ฉํ๊ณ ์ ํ๋ TotalActivityView๊ฐ scope์ ์๋ค๋ ๋ฉ์์ง๊ฐ ๋ณด์๋ค.
๊ณ์ ์์นํ๊ณ , ์ฝ์ง์ ํ๋ค ๋ณด๋,, ๋ด๊ฐ extension๋ค์ add target์ผ๋ก ํด์คฌ์ผ๋ฏ๋ก,, ์๋ค๋ค์ ๋ชจ๋ ํ๊น์ ์ถ๊ฐํด์ค์ผ ํ๋ค.
์ง๋ ํ๋ก์ ํธ ๋น์์๋ ์ด๊ฒ๋๋ฌธ์ ์ฝ์ง์ ๊ฝค ํ์๋๋ฐ.. ์์ฐจ์ฐจ ์ด๊ฑธ ๋ ์์๋ค๋..
์ค๋ ์ฝ์ง ์ํ๊ณ ์ง๊ธ์ด๋ผ๋ ์์์ผ๋ ๋คํ์ด๋ค.
๋จผ์ , viewController์ ์ค๋ฅธ์ชฝ inspector์์ target์ ActivityReport๋ฅผ ์ฒดํฌํด์ฃผ์๋ค.
๊ทธ๋ฆฌ๊ณ , TotalActivityView์์๋ ๋ฉ์ธ ํ๋ก์ ํธ ํ๊น์ ์ถ๊ฐํด์ฃผ์๋ค.
๊ทธ๋ฌ๋๋, ์ด์ TotalActivityView๋ฅผ ์ ์ฐพ์ ๋น๋๊ฐ ์ฑ๊ณตํ๋ค.
๋ง์ฝ ์๋๋ค๋ฉด, ์๋จ์ Product -> Clean Build Folder๋ฅผ ๊ผญ ํ๊ธธ!!
์์ฐจ์ฐจ ๊ทธ๋ฐ๋ฐ ํ๋ฉด์๋ ์๋ฌด๊ฒ๋ ๋ณด์ด์ง ์์๋๋ฐ, ๊ทธ ์ด์ ๊ฐ SceneDelegate.swift ํ์ผ์ ์์ ํ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค..
ํ์ฌ๋ StoryBoard๋ก ์ฐ๊ฒฐ๋๋๋ก ๋ผ ์์ด ์ด๊ฑธ ๋ฐ๊ฟ์ค์ผ ํ๋ค.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
let viewController = MainViewController()
window.rootViewController = viewController
window.makeKeyAndVisible()
self.window = window
}
์ด๋ ๊ฒ ํ๊ณ ์คํํ๋ ํ๋ฉด์ด ์ ์ฐ๊ฒฐ๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค !
์ง๊ธ์ ์๋์ผ๋ก ์ ๊ณต๋๋ view๋ง ์ฐ๊ฒฐํ๋๋ฐ, ๊ทธ๋ ๊ธฐ์ ์ค์ ๊ธฐ๊ธฐ์์ ์ฌ์ฉํ ์ฑ์ ๋ํ ์๊ฐ๋ค์ด ๋์ค๋๊ฒ ์๋๋ผ, ๋ด๊ฐ ํด๋น VC๋ฅผ ํธ์ถํ ๋ ๋ฃ์ argument ๊ฐ์ด ๊ทธ๋๋ก ๋ณด์ฌ์ง๊ณ ๋ง ์์๋ค.
์ ์คํ ๊ฒฐ๊ณผ๋ ๊ธฐ์กด์ extension์์ ์ค ์ฝ๋๋ฅผ rootView๋ก ์ฐ๊ฒฐํด ์คํํ ๊ฒฐ๊ณผ์ด๋ค.
์ด์ , ActivityReport๋ฅผ ์ง์ ์ฐ๊ฒฐํด์ ๋ณด์ฌ์ค์ผ ํ๋ค !!
๊ทธ ์ ์, ์คํฌ๋ฆฐํ์์ผ๋ก ๊ธฐ๊ธฐ์ ์๋ ์ ์ฒด ์ฑ์ ๊ฐ์ ธ์ ์ ํ์์ผ๋ณด์ !
์์งํ ๋งํ๋ฉด,, ์ฌ๊ธฐ์ ์ฝ์ง์ ์ง์ง ์๋ง์ด ํ๋ค.
๊ฒฐ๊ตญ ์ ๊ทผ ๊ถํ์ ๋จผ์ ํ์ฉํด์ค์ผํ๋ค๋๊ฑธ ๋ค๋ฆ๊ฒ ๊นจ๋ฌ์๋ค..
1. ์คํฌ๋ฆฐํ์ ์ ๊ทผ ๊ถํ ์์ฒญํ๊ธฐ
๋จผ์ ์ ๊ทผ ๊ถํ์ ํ์ฉํ๊ธฐ ์ํด์๋ family controls๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ฒ Family Controls๋ฅผ ์ถ๊ฐํ๋ฉด ๋๋ค.
์์ฐจ์ฐจ Family Controls์ ์ผ๋ถ๋ง ์ฝ๊ณ ๋ด ํ๋ก์ ํธ์์๋ ์ฐ์ง ์์๊ฑฐ๋ผ๊ณ ์๋ถํ๋๋ฐ..ใ ใ ใ ใ
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
// SwiftUI ๋ทฐ๋ฅผ ํธ์คํ
ํ๋ UIHostingController๋ฅผ ์์ฑ - ์ฆ SwiftUI ์ฐ๊ฒฐํ๊ธฐ
let totalActivityView = TotalActivityView(totalActivity: "hello")
let hostingController = UIHostingController(rootView: totalActivityView)
// UIKit์ UIWindow ์ค์
window = UIWindow(windowScene: windowScene)
window?.rootViewController = hostingController
window?.makeKeyAndVisible()
// ์คํฌ๋ฆฐํ์ ๊ถํ ๊ถํ ์์ฒญ
Task {
let center = AuthorizationCenter.shared
do {
try await center.requestAuthorization(for: .individual)
} catch {
print("Fail: \(error)")
}
}
}
์ด๋ ๊ฒ ๊ถํ ์์ฒญ์ ์ฐ๊ฒฐํ๋ฉด ๋๋ค !!
2. ๊ธฐ๊ธฐ์ ์ฑ ๋ฆฌ์คํธ ๋ณด์ฌ์ฃผ๊ธฐ
์ด์ ๊ธฐ๊ธฐ์ ์๋ ๋ชจ๋ ์ฑ์ ๋ฆฌ์คํธ๋ฅผ ๋ณด์ฌ์ค์ผ ํ๋ค.
import UIKit
import SwiftUI
import FamilyControls
struct AppListView: View {
// ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด @State ์ฌ์ฉํ๊ธฐ
// FamilyActivitySelection()์ ์ฌ์ฉ์๊ฐ ์ ํํ ๊ฐ์กฑ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ํ๋ด๋ ๊ฐ์ฒด.
@State var selection = FamilyActivitySelection()
// isPresented๋ familyActivityPicker๊ฐ ํ๋ฉด์ ํ์๋๋์ง ํต์ ํจ
@State var isPresented = false
var body: some View {
// VStack์ ์์ง์ผ๋ก ๊ทธ๋ฆฌ๊ธฐ
VStack {
Button {
// ๋ฒํผ์ด ํด๋ฆญ๋๋ฉด isPresented ์ํ๋ฅผ true๋ก ์ค์
isPresented = true
} label: {
// ๋ฒํผ์ ๋ ์ด๋ธ ์ง์ ํ๊ธฐ
Text("show app list")
}
}
// .familyActivityPicker๋ family activity๋ฅผ ์ ํํ ์ ์๋ Picker ํ๋ฉด์ ๋ณด์ฌ์ฃผ๊ธฐ
// isPresented๊ฐ true์ผ ๋ Picker๊ฐ ํ์.
// selection์ ์ฌ์ฉ์๊ฐ ์ ํํ ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํจ.
.familyActivityPicker(isPresented: $isPresented, selection: $selection)
}
}
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์ง๋ฉด ๋๋๋ฐ, ๋๋ SwftUI๋ฅผ ์ ํ ์์ง ๋ชปํด์ ์ฃผ์์ผ๋ก ์ ๋ฆฌ๋ฅผ ์ข ํด๋๋ค.
๋๋ ์๋ก์ด ํ์ผ์ ๋ง๋ค์ด์ ๋ฆฌ์คํธ ๋ถ๋ฌ์ค๋ ๋ถ๋ถ์ ๊ตฌํํ๋๋ฐ, ์ด ๋ ๋น๋๋ ์คํจํ๊ณ , ์คํจ ๋ฉ์์ง๊ฐ ์๊พธ ๋ณด์ฌ์ก๋ค ์ฌ๋ผ์ก๋ค.
์ค์๋ ๋ฐ๋ณต๋๋ฉด ์ค๋ ฅ์ธ๋ฐ ๋ ํ๊น ์ค์ ๋ฌธ์ ์๋ค.
์ง๊ธ familyCotrol์ ์ฌ์ฉํ๋ ค ํ๊ธฐ ๋๋ฌธ์ target์ activity report๋ฅผ ์ถ๊ฐํด์ค์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋น๋ํ๋, ์ด๋ ๊ฒ ์ ๋์ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด์ ๋ฆฌ์คํธ์์ ์ ํํ ์ฑ๋ค์ ์ฝ์์ ์ถ๋ ฅํด๋ณด๊ณ , ์ ํํ ์ฑ๋ค์ ์ฌ์ฉ์ ์ ํํด๋ณด์.
3. ์ ํํ ์ฑ ์ฌ์ฉ ์ ํํ๊ธฐ
๋จผ์ ์ ํํ ์ฑ๋ค์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ชจ๋ธ์ ๋ง๋ค์ด์ค๋ค.
import SwiftUI
import FamilyControls
import ManagedSettings
// ObservableObject ํ๋กํ ์ฝ์ ์ฑํํ Model ํด๋์ค ์ ์
class Model: ObservableObject {
// ์ด ํด๋์ค์ ๊ณต์ ์ธ์คํด์ค ์์ฑ (์ฑ๊ธํค ํจํด)
static var shared = Model()
// ManagedSettingsStore์ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ฌ ์ค์ ์ ๊ด๋ฆฌํ ์ ์๊ฒ ํจ
let store = ManagedSettingsStore()
// ์ฌ์ฉ์๊ฐ ์ ํํ๋ ค๋ ์ฑ ๋ฐ ์นดํ
๊ณ ๋ฆฌ ์ ํ์ ์ ์ฅํ๋ ๋ณ์, ๋ณ๊ฒฝ๋ ๋๋ง๋ค UI ์
๋ฐ์ดํธ
@Published var selectedtoLimit: FamilyActivitySelection
// ์ด๊ธฐํ ๋ฉ์๋: selectedtoLimit์ ์๋ก์ด FamilyActivitySelection ๊ฐ์ฒด๋ก ์ด๊ธฐํ
init() {
selectedtoLimit = FamilyActivitySelection()
}
// ์ฌ์ฉ์๊ฐ ์ ํํ ์ฑ๊ณผ ์นดํ
๊ณ ๋ฆฌ์ ๋ํด ์ฐจ๋จ ์ ํ์ ์ค์ ํ๋ ํจ์
func setShieldRestrictions() {
// ์ฌ์ฉ์๊ฐ ์ ํํ ์ฑ๊ณผ ์นดํ
๊ณ ๋ฆฌ ์ ํ์ ๊ฐ์ ธ์ด
let applications = Model.shared.selectedtoLimit
// ์ฑ ์ฐจ๋จ์ ์ค์ , ์ ํ๋ ์ฑ์ด ์์ผ๋ฉด nil๋ก ์ค์
store.shield.applications = applications.applicationTokens.isEmpty ? nil : applications.applicationTokens
// ์ฑ ์นดํ
๊ณ ๋ฆฌ ์ฐจ๋จ ์ค์ , ์ ํ๋ ์นดํ
๊ณ ๋ฆฌ๊ฐ ์์ผ๋ฉด nil๋ก ์ค์
store.shield.applicationCategories = applications.categoryTokens.isEmpty
? nil
: ShieldSettings.ActivityCategoryPolicy.specific(applications.categoryTokens)
}
}
์ด์ ๋ชจ๋ธ์ ์ถ๊ฐํ์ผ๋, ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ๋ถ๋ถ๋ ๋ชจ๋ธ์ ๋ด๊ณ ๋ชจ๋ธ ๋จ์๋ก ๊ด๋ฆฌํ ์ ์๋๋ก ์กฐ๊ธ ์์ ํด์ค๋ค.
struct AppListView: View {
// ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด @State ์ฌ์ฉํ๊ธฐ
// FamilyActivitySelection()์ ์ฌ์ฉ์๊ฐ ์ ํํ ๊ฐ์กฑ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ํ๋ด๋ ๊ฐ์ฒด.
@State var selection = FamilyActivitySelection()
// isPresented๋ familyActivityPicker๊ฐ ํ๋ฉด์ ํ์๋๋์ง ํต์ ํจ
@State var isPresented = false
@EnvironmentObject var model: Model
var body: some View {
// VStack์ ์์ง์ผ๋ก ๊ทธ๋ฆฌ๊ธฐ
VStack {
Button {
// ๋ฒํผ์ด ํด๋ฆญ๋๋ฉด isPresented ์ํ๋ฅผ true๋ก ์ค์
isPresented = true
} label: {
// ๋ฒํผ์ ๋ ์ด๋ธ ์ง์ ํ๊ธฐ
Text("show app list")
// .familyActivityPicker๋ family activity๋ฅผ ์ ํํ ์ ์๋ Picker ํ๋ฉด์ ๋ณด์ฌ์ฃผ๊ธฐ
// isPresented๊ฐ true์ผ ๋ Picker๊ฐ ํ์.
// selection์ ์ฌ์ฉ์๊ฐ ์ ํํ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ธ์ ์ ์ฅํจ.
}.familyActivityPicker(isPresented: $isPresented, selection: $model.selectedtoLimit)
}
// ์ดํ ์ ํํ ์ฑ๋ค์ ๋ํ shieldRestriction์ด ์คํ๋๋ค.
.onChange(of: model.selectedtoLimit, {
Model.shared.setShieldRestrictions()
})
}
}
๊ทธ๋ฆฌ๊ณ , ์คํฌ๋ฆฐํ์์ ๋ํ ๊ถํ ์์ฒญ์ AppDelegate๋ก ๋๊ฒจ์ค๋ค.
// AppDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
// `Model.shared`์ ์ธ์คํด์ค๋ฅผ ์์ฑ
let model = Model.shared
// SwiftUI์ AppListView๋ฅผ ์ค์
let contentView = AppListView().environmentObject(model)
// ์๋ก์ด UIWindow๋ฅผ ์์ฑํ๊ณ ์ด๊ธฐ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ก ์ค์
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก, SceneDelegate๋ฅผ ์์ ํด์ค๋ค. ์ฌ๊ธฐ์ ๋ชจ๋ธ์ ๋ด๋๋ก ์์ ํ๊ณ , ๊ถํ ํ์ฉ ๋ถ๋ถ์ ์์์ ํ ๊ฒ ์ฒ๋ผ AppDelegate๋ก ๋๊ฒจ์คฌ๋ค.
// SceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
// `Model.shared`์ ์ธ์คํด์ค๋ฅผ ์์ฑ
let model = Model.shared
// SwiftUI์ AppListView๋ฅผ ์ค์
let contentView = AppListView().environmentObject(model)
// ์๋ก์ด UIWindow๋ฅผ ์์ฑํ๊ณ ์ด๊ธฐ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ก ์ค์
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
์ด๋ ๊ฒ ํ๊ณ , ์ฑ์ ์คํํด๋ณด์ !
์คํ ๊ฒฐ๊ณผ
์๋ ์ด๋ ๊ฒ ๊ฐ๋จํ ๊ธฐ์ ๊ฒ์ฆ์ ๊ทธ๋๋ ์๊ทธ๋ ๊ฒ ์ฝ์งํ๊ณ ํ๋ค์ดํ์๊น..
์๊ฐ์ด ์ด๋ฐํ๋ค๋ ์ด์ ๋ก reference๋ถํฐ ์ฐพ๊ณ , ๋ ๋ค ์คํํด๋ณด๊ณ ๋์ด๊ฐ๋ ๊ณผ๊ฑฐ์ ๋.. ๋ฐ์ฑํ๋ผ..
์ด์ ์ ํ ๊ณต์๋ฌธ์ ๊ตฌ์กฐ๋ ์ด๋์ ๋ ๊ฐ์ด ์กํ๊ณ , ์์ง ๊ทธ๊ฑธ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋๋ ๋ชป์ง๊ฒ ์ง๋ง,, ๋ญ,, ์์ผ๋ก ์ฐจ๊ทผ์ฐจ๊ทผ ํด๋ด์ผ๊ฒ ๋ค !!
๋ค์ ๊ธ์์๋ ์ด์ ์ฐ๋ฆฌ ํ๋ก์ ํธ์ ์ฃผ๊ธฐ๋ฅ์ ๊ตฌํํด๋ด์ผ์ง !
์ฐธ๊ณ ์๋ฃ
https://hongz-developer.tistory.com/246
'๐ iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] tableView ์ ์๋ ๊ตฌ๋ถ์ ์์ ๊ธฐ (0) | 2024.11.19 |
---|---|
[iOS] apple login ๊ตฌํํ๊ธฐ (2) | 2024.09.14 |
[iOS] ScreenTime API ๋? (8) | 2024.09.11 |
[iOS] debug ๋ชจ๋์์ release ๋ชจ๋๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ (2) | 2024.07.27 |
[iOS] Main storyboard์ Launch storyboard ์ฐจ์ด (4) | 2024.03.16 |