스크린 타임은
1. 사용자와 가족이 앱과 웹사이트를 얼마나 자주 사용하는지 추적하고,
2. 제한을 설정하여 시간을 관리하고,
3. 가족 구성원과 사용량을 공유하여 기기 사용 현황을 파악할 수 있으며,
4. 마지막으로 자녀가 누구와 소통하는지 등을 관리할 수 있다.
iOS 15
iPadOS 15
앱에서 스크린 타임에서 사용할 수 있는 제한 사항에 직접 액세스할 수 있다.
가족 제어는 트위터의 개인정보 보호정책을 주도한다.
가족 공유를 활용하여 보호자 승인 없이 스크린 타임 API에 액세스 할 수 없도록 한다.
보호자의 승인을 받은 앱은 보호자 승인 없이 기기에서 제거할 수 없다.
또한 앱과 웹 사이트를 나타내는 토큰을 제공하여 스크린 타임 API 전체에서 사용량을 모니터링하거나 제한하는 데 사용된다. (가족 그룹 외부에서는 볼 수 없도록 정보가 모두 보호된다.)
디바이스 활동은 앱을 실행하지 않고도 코드를 실행할 수 있는 기능을 제공한다.
앱에 웹 & 앱 사용을 모니터링하고 필요할 때 코드를 실행할 수 있는 새로운 방법을 제공한다.
디바이스 활동 일정과 이벤트
기기 활동 일정
: 시작될 때와 끝날 때 애플리케이션의 확장 프로그램을 호출하는 시간 창이벤트
: 유저가 기기 활동 일정의 사용 임계값에 도달할 때 내선 번호를 호출하는 사용량 모니터.앱은 어떤 유형의 사용량을 언제 모니터링할지 선언하기만 하면 된다.
보호자가 원하는 다른 앱의 사용량이 누적될 때까지
특정 앱에 대한 자녀의 액세스를 제한
하여 좋은 습관을 장려하는 것이 주 기능이다.
가족 제어에 대한 승인을 요청하는 방법: 프로젝트 설정과 패밀리 컨트롤 승인
먼저 Xcode의 해당 Taget에서 Capability를 추가한다.
// APP: 권한 요청하기
import FamilyControls
AuthorizationCenter.shared.requestAuthorization { result in
switch result {
case .success():
...
case .failure(let error):
...
}
}
내 앱이 이전에 이 iPhone에서 실행된 적이 없기 때문에 요청 승인은 경고와 함께 보호자의 승인을 요청한다. 허용을 탭하면 계속하려면 보호자에게 Apple ID와 비밀번호로 인증하라는 메시지가 표시된다.
이때 보호자가 인증에 성공하면 요청인증을 호출하면 다시 경고 메시지를 표시하지 않고 자동으로 성공 여부를 반환한다.
오용을 방지하기 위해 로그인한 iCloud가 가족 공유를 사용하는 자녀가 아닌 경우 요청 승인은 실패를 반환한다.
앱에서 스크린 타임 API를 사용할 수 있도록 준비하는 것은 이렇게 쉽다.
가족 제어로 인증하면 앱에 다른 권한도 부여된다.
on-device web content filters
는 앱에 포함될 수 있으며 자동으로 설치되고 제거할 수 없음자녀 보호 앱은 자녀가 앱을 실행하지 않을 가능성이 높은데도 자녀의 기기에서 코드가 실행되도록 하는 것이 어려운 부분이다.
스크린 타임 API의 경우, 기기 활동으로 백그라운드 코드 실행을 수행할 수 있는 새로운 방법을 만들었다.
기기 활동 확장은 나머지 스크린 타임 API와 상호 작용하는 주요 방법이 될 것이다.
반복되는 일정에 따라 보호자가 선택한 사용 금지 앱을 보호
자녀의 기기에서 앱이 실행되지 않고있어도, 보호자가 금지한 앱이 실행되지 않도록 스케줄을 설정하여 반복적으로 작동하게 하는 기능이다.
이 Extension을 구현하려면 DeviceActivityMonitor
를 기본 클래스로 서브 클래싱 하여 모니터를 만들어주자.
// EXTENSION: Create a DeviceActivityMonitor
class MyMonitor: DeviceActivityMonitor {
override func intervalDidStart(for activity: DeviceActivityName) {
super.intervalDidStart(for: activity)
}
override func intervalDidEnd(for activity: DeviceActivityName) {
super.intervalDidEnd(for: activity)
}
}
이 함수들은 내 일정이 시작되고 종료된 후 기기를 처음 사용할 때 호출된다.
이제 DeviceActivityName
과 DeviceActivitySchedule
을 만들어야 한다.
// APP: Monitor a DeviceActivitySchedule
import DeviceActivity
// 1. 활동을 참조할 수 있는 이름 생성
extension DeviceActivityName {
static let daily = Self("daily")
}
// 2. 활동을 모니터링할 시간 범위 설정
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 0, minute: 0),
intervalEnd: DateComponents(hour: 23, minute: 59),
repeat: true
)
// 3. center를 통해 방금 생성한 이름과 일정으로 `startMonitoring` 호출
let center = DeviceActivityCenter()
try center.startMonitoring(.daily, during: schedule)
위 코드를 통해 일정이 시작되고 끝날 때마다 MyMonitor
가 활동 이름(DeviceActivityName
)과 함께 호출된다.
// APP: Choose the Apps to Discourage
import FamilyControls
import SwiftUI
@StateObject var model = MyModel()
@State var isPresented = false
var body: some View {
Button("Select Apps to Discourage") {
isPresented = true
}
.familyActivityPicker(isPresented: $isPresented, selection: $model.selectionTpDiscourage)
}
FamilyControls 프레임워크에는 작업을 위한 SwiftUI 요소인 familyActivityPicker
(가족 활동 선택기)가 있다.
기본 앱의 UI에서 이 피커를 표시하고 보호자가 앱 or 웹을 카테고리 목록에서 선택한다.
이 피커의 반환값인 불투명 토큰(?)을 사용하여 제한 설정을 할 수 있다.
버튼을 통해 불러온 피커는 반환값을 모델의 속성에 바인딩한다.($model.selectionTpDiscourage
)
// EXTENSION: Shied the Discouraged Apps
import DeviceActivity
import ManagedSettings // 추가
class MyMonitor: DeviceActivityMonitor {
let store = ManagedSettingsStore() // 추가
override func intervalDidStart(for activity: DeviceActivityName) {
super.intervalDidStart(for: activity)
let model = MyModel() // 모델 인스턴스
let applicationos = model.selectionToDiscourage.applications // 선택된 앱 List
store.shield.applications = applications.isEmpty ? nil : applications // store 등록
}
override func intervalDidEnd(for activity: DeviceActivityName) {
super.intervalDidEnd(for: activity)
store.shield.applications = nil
}
}
// APP: Adding a DeviceActivityEvent
import DeviceActivity
extension DeviceActivityName {
static let daily = Self("daily")
}
extension DeviceActivityEvent.Name { // 이벤트 이름 등록
static let encouraged = Self("encouraged")
}
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 0, minute: 0),
intervalEnd: DateComponents(hour: 23, minute: 59),
repeat: true
)
let model = MyModel()
let events = [DeviceActivityEvent.Name: DeviceActivityEvent] = [
.encouraged: DeviceActivityEvent( // 이벤트 이름에 맞는 이벤트 생성
applications: model.selectionToEncourage.applicationTokens
threshold: DataComponents(minute: minutes)
)
]
let center = DeviceActivityCenter()
try center.startMonitoring(.daily, during: schedule, events: events) // 이벤트 등록
권장 앱 사용 시간을 충분히 누적한 다음 차단을 해제하는 방법
// EXTENSION: Implement theh Threshold Function
import DeviceActivity
import ManagedSettings
class MyMonitor: DeviceActivityMonitor {
let store = ManagedSettingStore() // store 인스턴스
...
// 허용된 앱의 사용량이 누적되었을 때 호출됨
override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) {
super.eventDidReachThreshold(event, activity: activity)
store.shield.applications = nil // 해당 이벤트가 충족되면 제한 해제
}
}
앱의 브랜딩과 기능에 맞게 shields를 커스텀 가능
// EXTENSION: Create a ShieldConfigurationProvider
import ManagedSettings
import ManagedSettingsUI
class MyShieldConfiguration: ShieldConfigurationProvider {
override func configuration(for application: Application) -> ShieldConfigutaion {
return ShieldConfiguration(
backgroundEffect: ...
backgroundColor: ...
icon: ...
title: ShieldConfiguration.Label(
text: ...
color: ...
),
subtitle: ShieldConfiguration.Label(
text: ...
color: ...
)
)
}
}
위 함수를 통해 Block 되었을 때의 화면을 커스텀할 수 있다.
// EXTENSION: Create a ShieldActionHandler
import ManagedSettings
class MyShieldActionExtension: ShieldActionHandler {
override func handle(action: ShieldAction,
for application: Application,
completionHandler:
@escaping (ShieldActionResponse) -> Void {
switch action {
case .primaryButtonPressed:
completionHandler(.defer)
case .secondaryButtonPressed:
completionHandler(.close)
@unknown default:
fatalError()
}
}
}
위 함수를 통해 커스텀 핸들러를 지정할 수 있다.
현재 진행중인 Tublock 앱을 완성하기 위해 필요한 Screen Time API!
위 내용에서는 가족 공유가 사용된 예시만 있어서 없는 경우는 내가 직접 만들어봐야한다.
이 API를 사용하여 앱이 완성되면 어떻게 사용했는지도 문서화시켜 공유해볼 예정이다.
yeni가 초대해주신 WWDC 스터디 덕분에 한 주에 4개씩 공부할 수 있게됐다. 헤헤😁
안녕하세요 도연님 덕분에 스크린타임에 대한 정보 많이 얻어갑니다 :)
한가지 질문이 있는데요.
block한 앱을 특정시간만큼 사용할 수 있게 해주고 특정시간이 지나면 다시 앱을 block 하는 기능을 개발하려고 하는데,
위에서 말씀해주신 코드중에 DeviceActivityEvent 쪽을 사용하면 될까요?
아래처럼 1분 후 앱 block 하는 기능인줄 알았으나 적용이 되지 않아 event에 대해 잘못 알고 있는것 같아 질문드립니다 ㅠㅠ