WWDC22 What's new in Screen Time API
https://developer.apple.com/videos/play/wwdc2022/110336/
Screen Time API?
Screen Time API는 iOS15에서 처음 소개되었다.
이 API는 3가지의 프레임워크로 표현된다. Family Controls, Managed Settings, Device Activity 이다.
Family Controls
- Screen Time API의 접근 권한 부여 (일종의 게이트역할)
- 자녀 보호 앱이 삭제되는 것을 방지함 (Prevents removal and circumvention)
- 사용자의 개인정보 보호(앱, 웹 사이트 식별에 opaque token 사용)
Managed Settings
이 프레임워크도 마찬가지로 앱에 제약을 적용할 수 있다.
- 앱 사용 제한
- 웹 트래픽 필터링
- 앱의 브랜딩과 기능에 맞게 앱과 웹의 제악조건을 걸 수 있다.
Device Activity
- 앱, 웹의 사용량을 넘어가면 특정 코드가 실행되도록 할 수 있다.
iOS16에서 업데이트된 Screen Time API
"Worklog"라는 데모 앱으로 새로운 점들을 살펴보자.
해당 앱은 특정 수치들이 충족될 때까지 특정 앱의 사용을 제한하는 앱이다.
Screen Time API로 앱 사용에 어떻게 제한을 거는지 알아보도록 하자!
Family Controls
- iOS15 : iCloud 승인을 통해서만 자녀의 기기를 승인할 수 있었다.
- iOS16
- 사용자 기기에서 개별 사용자를 승인할 수 있게 되었다. (individual users authorize themselves)
- 하나의 기기에서 여러 앱을 사용할 수 있다??
- iCloud 로그아웃과 앱 삭제에 대한 내적 제한이 적용되지 않는다.
새로운 승인 방법을 알아보자! 아래는 Worklog 데모 앱의 코드이다.
// APP: Request Authorization
import SwiftUI
import FamilyControls
@main
struct Worklog: App {
let center = AuthorizationCenter.shared
var body: some Scene {
WindowGroup {
VStack {..}
.onAppear {
Task {
do {
try await center.requestAuthorization (for: .individual)
} catch {
print("Failed to enroll Aniyah with error: \(error)")
}
}
}
}
}
}
- 앱이 실행되면 FamilyControls에 대한 승인을 요청해야 한다. (관문)
- `AuthorizationCenter.shared`을 사용하여 Worklog 앱이 시작될 때 승인을 요청한다.
- 요청 후에는 승인이 되거나(try) 오류가 발생(catch)한다.
iPhone에서 Worklog 앱을 처음 실행할 경우, FamilyControls에 대한 승인을 요청한다. 해당 메서드는 try-catch문의 requestAuthorization(for:)이다.
do {
try await center.requestAuthorization (for: .individual)
} catch {
print("Failed to enroll Aniyah with error: \(error)")
}
이 메서드는 alert 창을 띄워 승인을 요청한다. 허용을 하면 기기의 암호(FaceID, TouchID 등)를 사용하여 인증하는 메세지가 표시된다. 인증이 잘 마무리되면 request- 메서드가 또 호출되어도 경고 메세지가 다시 표시되지 않는다.
앱이 FamilyControls로 승인되었다. 그러면 iPhone의 설정에서 해당 앱(여기서는 Worklog)에 대한 스위치가 2개 추가된다.
- Apps with Screen TimeAccess List
- Screen Time Restrictions
나중에는 이 스위치로만 FamilyControls의 앱 승인을 끄고 켤 수 있다.
이렇게 따로 승인을 조절하는게 이번에 새롭게 업데이트된 부분이다 (!!)
Managed Settings
iOS16에서는 ManagedSettingsStore를 더 사용하기 쉽게 되었따! 그게 몰까잉
-> 현재 사용자가 기기에 설정을 적용하는 데이터 저장소. 설정 값이 저장된 곳이 ManagedSettingsStore이다.
iOS15에서는 프로세스 하나당 하나의 ManagedSettingsStore이 허용되었다.
그러나 iOS16에서는 프로세스 하나당 최대 50개까지 만들 수 있다.
단, 지켜져야 하는 점은 각 ManagedSettingsStore는 고유의 이름을 가져야 한다!
- 앱과 앱의 확장 프로그램은 같은 세팅 값을 공유할 수 있다.
- 각 스토어의 세팅을 한번에 제거할 수 있다.
Worklog 앱이 실행되고 기기가 승인되고 나면, 아래의 코드가 수행되면서 'gaming'이라는 ManagedSettingsStore을 만든다.
// APP: Setup the default restrictions for our app
import ManagedSettings
extension ManagedSettingsStore. Name {
static let gaming = Self("gaming")
func worklogSetup () {
let gamingCategory = ActivityCategoryToken (...)
let gamingStore = ManagedSettingsStore (named : •gaming)
gamingStore.shield.webDomainCategories = .specific([gamingCategory])
}
}
'gaming' ManagedSettingsStore은 해당 앱이 모든 게임 웹 사이트를 차단하도록 설정되어 있다.
마찬가지로 SNS앱과 웹 사이트를 차단하는 'social'이라는 ManagedSettingsStore도 만들 수 있다.
// APP: Shield Social category
import ManagedSettings
extension ManagedSettingsStore. Name {
static let gaming = Self("gaming")
static let social = Self("social")
}
func worklogSetup () {
let gamingCategory = ActivityCategoryToken ( ...)
let gamingStore = Managed$ettingsStore (named: .gaming)
gamingStore.shield.webDomainCategories = .specific([gamingCategory])
let socialCategory = ActivityCategoryToken ( ...)
let socialStore = ManagedSettingsStore (named: .social)
socialStore.shield.applicationCategories = .specific ([socialCategory])
socialStore.shield.webDomainCategories = .specific([socialCategory])
}
근데 SNS 앱 사용을 특정 시간에만 가능하도록 허용하고 싶을 수도 있다. 'Allow for evenings' 버튼을 누르면 오후 5시~8시 사이에만 SNS 앱을 사용할 수 있도록 허용하는 DeviceActivitySchedule을 생성할 수 있다. 아래는 해당 코드이다.
// APP: Schedule Social Media between 5 and 8 PM
import SwiftUI
import DeviceActivity
extension DeviceActivityName {
static let activity = Self("activity")
}
struct Worklog: App {
let deviceActivityCenter = DeviceActivityCenter ()
var body: some Scene {
VStack {
Text ("Social Media")
Button ("Allow for Evenings", action: {
try? deviceActivityCenter.startMonitoring(.activity,
during: DeviceActivitySchedule (
intervalStart: DateComponents (hour: 17),
intervalEnd: DateComponents (hour: 20),
repeats: true
)
)
})
}
}
}
오후 5시가 되면 DeviceActivityMonitor가 해당 ManagedSettingsStore인 'social'에 대한 제한을 해제한다. 오후 8시가 지나면 다시 SNS와 웹사이트의 제한을 시작한다. 이렇게 앱 사용 시간을 조절할 수도 있다!
// MONITOR EXTENSION: Handle Social category at start/end of interval
import DeviceActivity
import ManagedSettings
class WorklogMonitor: DeviceActivityMonitor {
let database = BarkDatabase ( )
override func intervalDidStart(for activity: DeviceActivityName) {
super.intervalDidStart(for: activity)
let socialStore = ManagedSettingsStore (named: .social)
socialStore.clearAllSettings()
}
override func intervalDidEnd(for activity: DeviceActivityName) {
super.intervalDidEnd (for: activity)
let socialStore = ManagedSettingsStore (named: .social)
let socialCategory = database. socialCategoryToken
socialStore.shield.applicationCategories = .specific([socialCategory])
socialStore.shield.webDomainCategories = .specific( [socialCategory])
}
}
ManagedSettingsStore은 각각 'gaming', 'social'로 이름 붙여 각각 만들어줬다. 그러므로 'social'이라는 이름의 ManagedSettingsStore을 삭제하여도 'gaming'에는 영향을 미치지 않아 게임 사이트에 대한 제한은 유효하다.
이게 다 ManagedSettingsStore에 이름을 붙여서 여러 개를 만드는 기능이 추가되었기에 가능한 이야기이다!
Device Activity
iOS15에서는 앱, 웹 사이트에 대한 사용량 허용치와 사용 시간대에 반응했다.
iOS16에서는 앱에서 SwiftUI를 사용하여 완전히 맞춤화된 사용 보고서를 만들 수 있게 되었다.
또한 사용량 데이터는 확장 프로그램으로 제공되어서 사용자에게 표시될 데이터와 화면에 표현될 방식을 커스텀할 수 있게 되었다!
DeviceActivityReport << 사용자에게 완벽한 보안과 사용자 경험을.. 프라이버시를 지켜줌다.
// APP: Top-level view import SwiftUI
import DeviceActivity
extension DeviceActivityReport. Context {
static let pieChart = Self("Pie Chart")
}
@main
struct Worklog: App {
private let thisWeek = DateInterval(...)
@State private var context: DeviceActivityReport.Context = .pieChart
@State private var filter = DeviceActivityFilter (segment: daily (during: thisWeek))
var body: some Scene {
WindowGroup {
GeometryReader { geometry in
VStack(alignment: leading) {
DeviceActivityReport (context: context, filter: filter)
.frame (height: geometry.size.height * 0.75)
}
}
}
}
}
// REPORT EXTENSION: Configure Custom Device Activity Report
import SwiftUI
import DeviceActivity
struct PieChartReport: DeviceActivityReportScene {
let context: DeviceActivityReport.Context = .pieChart
let content: (PieChartView.Configuration) -> PieChartView
func makeConfiguration (representing data: [DeviceActivityData])
-> PieChartView. Configuration {
var totalUsageByCategory: [ActivityCategory:TimeInterval]
totalUsageByCategory = data.map (...)
return PieChartView.Configuration(totalUsageByCategory: totalUsageByCategory)
}
}
DeviceActivity 프레임워크는 새로 사용량 데이터를 가져올 때마다 makeConfiguration 메서드를 호출하므로 직접 호출할 필요가 없다.
이제 이 사용량 데이터를 기반으로 하는 파이차트를 화면에 그려보자.
// REPORT EXTENSION: Configure Custom Device Activity Report
import SwiftUI
import DeviceActivity
struct PieChartView: View {
struct Configuration {
let totalUsageByCategory: [ActivityCategory:TimeInterval]
}
let configuration: Configuration
var body: some View {
// A complex view that renders a bar graph based on Aniyah's usage per category.
PieChart (usage: configuration.totalUsageByCategory)
}
}
DeviceActivityData로 PieCharView.Configuration이 파이 차트 뷰에 대한 뷰모델의 역할을 수행한다.
확장 프로그램의 body에서 DeviceActivityReport를 정의하여 맞춤형 SwiftUI 보고서를 표현할 수 있다.
// REPORT EXTENSION: Draw Custom Device Activity Report
import SwiftUI
import DeviceActivity
@main
struct WorklogReportExtension: DeviceActivityReportExtension {
var body: some DeviceActivityReportScene {
PieChartReport { configuration in
PieChartView (configuration: configuration)
}
}
}
쨔쟈룽
요약.