SlideShare ist ein Scribd-Unternehmen logo
1 von 24
Downloaden Sie, um offline zu lesen
GameplayKit 으로
상태표시 UI 쉽게 만들기
노수진 · 네이버웹툰
contact@soojin.ro
샘플코드 : https://github.com/nsoojin/VoiceControlSample-iOS
샘플코드 : https://github.com/nsoojin/VoiceControlSample-iOS
상태 UI
attending
detecting listening processing
reporting
3가지 정의 요소
- 상태 (a list of states)
- 변화의 조건 (transition)
- 초기 상태 (initial state)
유한한 개수의 상태 중에서 한 번에 오로지 하나의 상태만을 가질 수 있고,
어떠한 사건에 의해 한 상태에서 다른 상태로 변화할 수 있다.
Finite-State Machines 유한 상태 기계
GameplayKit
Randomization
Entities and Components
State Machines
The Minmax Strategist
Pathfinding
Agents, Goals, Behaviors
Rule Systems
GameplayKit
State Machines
Use this architecture to untangle complex procedural code in your gameplay designs.
State MachinesGameplayKit
GKState
- 상속 받아서, 오버라이드를 통해 상태별 동작과 전환(transition)의 조건을 정의
- State에 (1) 진입할 때, (2) 탈출할 때, 혹은 (3) State가 지속되는 동안 주기적으로 업데이트
GKStateMachine
- [GKState] 를 파라미터로 넘겨서 생성
- 생성 후 초기 상태 지정
UI 요구사항 분석
Core Animation Lottie
animationView(Lottie)
dotsContainerView(CoreAnimation)
Core Animation
internal final class DetectingState: VoiceState {
private func bounce(_ dot: UIView) {
let delayTime = 0.2 * Double(dot.tag - 1)
let bounce = CAKeyframeAnimation(keyPath: “position.y”)
bounce.beginTime = CACurrentMediaTime() + delayTime
bounce.values = [0, -6, 0, 6, 0]
bounce.keyTimes = [0, 0.25, 0.5, 0.75, 1.0]
bounce.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut),
CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn),
CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut),
CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)]
bounce.duration = 1.0
bounce.isAdditive = true
bounce.repeatCount = .infinity
dot.layer.add(bounce, forKey: DetectingState.animationKey)
}
}
Core Animation
internal final class ListeningState: VoiceState {
private func amplify(_ dot: UIView) {
let noise = random(min: 0, max: 0.3)
let animation = CASpringAnimation(keyPath: "bounds.size.height")
animation.beginTime = CACurrentMediaTime()
animation.toValue = dot.bounds.size.height * (regularized(magnitude) + noise)
animation.initialVelocity = -15
animation.damping = 7
animation.stiffness = 750
animation.autoreverses = true
animation.delegate = self
animation.isRemovedOnCompletion = true
dot.layer.add(animation, forKey: ListeningState.animationKey)
}
}
Lottie
internal final class ProcessingState: VoiceState {
private func animateProcessing() {
stateView.animationView.currentProgress = 0.16
stateView.animationView.loopMode = .loop
stateView.animationView.play(fromProgress: 0.16, toProgress: 0.32)
}
}
internal final class ReportingState: VoiceState {
private func animateReporting() {
stateView.animationView.currentProgress = 0.32
stateView.animationView.loopMode = .loop
stateView.animationView.play(fromProgress: 0.32, toProgress: 0.52)
}
}
GKState
internal final class DetectingState: VoiceState {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
animateBounce()
}
override func willExit(to nextState: GKState) {
super.willExit(to: nextState)
removeAnimation()
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
switch stateClass {
case is AttendingState.Type, is ListeningState.Type:
return true
default:
return false
}
}
}
(1) State 진입 시
(2) State 탈출 시
(3) Transition 조건
internal class VoiceState: GKState {
unowned let stateView: VoiceStateView
init(statusView: VoiceStateView) {
self.stateView = statusView
}
override func didEnter(from previousState: GKState?) {
switch self {
case is AttendingState, is ListeningState, is DetectingState:
stateView.animationView.isHidden = true
stateView.dotsContainerView.isHidden = false
case is ProcessingState, is ReportingState:
stateView.animationView.isHidden = false
stateView.dotsContainerView.isHidden = true
default:
break
}
}
}
GKState Best Practice
⚠ 바로 GKState을 상속받지 말고
공통 Superclass State로
공유 자원 및 반복 로직을 관리
internal class VoiceStateView: UIView {
private lazy var stateMachine: GKStateMachine = {
return GKStateMachine(states: [
AttendingState(statusView: self),
DetectingState(statusView: self),
ListeningState(statusView: self),
ProcessingState(statusView: self),
ReportingState(statusView: self)
])
}()
override func didMoveToWindow() {
state = .attending
stateMachine.enter(AttendingState.self)
}
}
GKStateMachine
진입할 수 있는 상태
초기 상태 지정
세팅 완료!
internal final class VoiceStateView: UIView {
@discardableResult
func setState(_ state: State) -> Bool {
let isNextStateValid = stateMachine.canEnterState(state.classType())
if isNextStateValid {
self.state = state
stateMachine.enter(state.classType())
}
return isNextStateValid
}
}
상태 변경
extension VoiceControl: JarvisDelegate {
func jarvis(_ jarvis: Jarvis, didChangeState state: JarvisState) {
switch state {
case .detecting:
voiceAgentView?.transcription = listeningStateDescription
voiceAgentView?.stateView?.setState(.detecting)
... 생략 ...
}
}
}
전부 합치기
class VoiceStateView: UIView
Jarvis(가칭)
class VoiceControl: UIControl
👋
희망 사항
- 상태뷰는 항상 view hierarchy 최상단에 위치
- 도중에도 쉽게 dismiss / cancel
- 어느 화면에나 쉽게 컨트롤 추가
UIResponder
var inputView: UIView?
var inputAccessoryView: UIView?
UIResponder
var inputView: UIView?
var inputAccessoryView: UIView?
var inputAccessoryView: UIView? { get }
inputView에 악세서리 뷰를 덧붙이고 싶을 때 사용한다.
인스턴스가 first responder가 되면 시스템이 이 뷰를 input view에 붙인 후 화면에 표시.
inputView가 nil이어도 악세서리 뷰는 표시됨 ✨
장점
- 애니메이션 : 네이티브 키보드처럼 show & hide
- 레이아웃 : Safe Area 대응 용이
- 뷰 계층 : os가 별도 UIWindow로 관리
- Responder chain : becomeFirstResponder(), resignFirstResponder()
resignFirstResponder()becomeFirstResponder()
마지막 총 정리
class VoiceControl: UIControl
override var inputAccessoryView: UIView? {
return voiceStateView
}
private var jarvis: Jarvis
private var voiceStateView: VoiceStateView
class VoiceStateView: UIView
var stateMachine: GKStateMachine
References
https://github.com/nsoojin/VoiceControlSample-iOS
https://developer.apple.com/documentation/gameplaykit/gkstatemachine
https://developer.apple.com/documentation/uikit/uiresponder
https://developer.apple.com/library/archive/documentation/General/Conceptual/GameplayKit_Guide/StateMachine.html#//apple_ref/doc/uid/TP40015172-CH7
https://en.wikipedia.org/wiki/Finite-state_machine
고맙습니다.

Weitere ähnliche Inhalte

Was ist angesagt?

스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration수홍 이
 
A python web service
A python web serviceA python web service
A python web serviceTemian Vlad
 
Datastructures in python
Datastructures in pythonDatastructures in python
Datastructures in pythonhydpy
 
Ch9 .Best Practices for Class-Based Views
Ch9 .Best Practices  for  Class-Based ViewsCh9 .Best Practices  for  Class-Based Views
Ch9 .Best Practices for Class-Based ViewsWilly Liu
 
Fabric.js — Building a Canvas Library
Fabric.js — Building a Canvas LibraryFabric.js — Building a Canvas Library
Fabric.js — Building a Canvas LibraryJuriy Zaytsev
 
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)Clément Wehrung
 
Internet VS World Wide Web
Internet VS World Wide WebInternet VS World Wide Web
Internet VS World Wide WebMadhuri Sharma
 
6 Key Elements to a Good Website
6 Key Elements to a Good Website6 Key Elements to a Good Website
6 Key Elements to a Good WebsiteWebs
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
Django interview Questions| Edureka
Django interview  Questions| EdurekaDjango interview  Questions| Edureka
Django interview Questions| EdurekaEdureka!
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation Salman Memon
 
Fabric.js @ Falsy Values
Fabric.js @ Falsy ValuesFabric.js @ Falsy Values
Fabric.js @ Falsy ValuesJuriy Zaytsev
 

Was ist angesagt? (20)

Navigation and Link
Navigation and LinkNavigation and Link
Navigation and Link
 
Links in Html
Links in HtmlLinks in Html
Links in Html
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
 
A python web service
A python web serviceA python web service
A python web service
 
Datastructures in python
Datastructures in pythonDatastructures in python
Datastructures in python
 
Css3
Css3Css3
Css3
 
Ch9 .Best Practices for Class-Based Views
Ch9 .Best Practices  for  Class-Based ViewsCh9 .Best Practices  for  Class-Based Views
Ch9 .Best Practices for Class-Based Views
 
Fabric.js — Building a Canvas Library
Fabric.js — Building a Canvas LibraryFabric.js — Building a Canvas Library
Fabric.js — Building a Canvas Library
 
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
 
Svg
SvgSvg
Svg
 
Sample Website Proposal Presentation
Sample Website Proposal PresentationSample Website Proposal Presentation
Sample Website Proposal Presentation
 
Internet VS World Wide Web
Internet VS World Wide WebInternet VS World Wide Web
Internet VS World Wide Web
 
6 Key Elements to a Good Website
6 Key Elements to a Good Website6 Key Elements to a Good Website
6 Key Elements to a Good Website
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
Django interview Questions| Edureka
Django interview  Questions| EdurekaDjango interview  Questions| Edureka
Django interview Questions| Edureka
 
Basic Web Concepts
Basic Web ConceptsBasic Web Concepts
Basic Web Concepts
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation
 
WordPress Complete Tutorial
WordPress Complete TutorialWordPress Complete Tutorial
WordPress Complete Tutorial
 
Lab#9 graphic and color
Lab#9 graphic and colorLab#9 graphic and color
Lab#9 graphic and color
 
Fabric.js @ Falsy Values
Fabric.js @ Falsy ValuesFabric.js @ Falsy Values
Fabric.js @ Falsy Values
 

Ähnlich wie GameplayKit으로 상태표시 UI 쉽게 만들기

Unity3D Scripting: State Machine
Unity3D Scripting: State MachineUnity3D Scripting: State Machine
Unity3D Scripting: State MachineSperasoft
 
Introduction to State Machines
Introduction to State MachinesIntroduction to State Machines
Introduction to State Machinescodeofficer
 
An Introduction To CQRS
An Introduction To CQRSAn Introduction To CQRS
An Introduction To CQRSNeil Robbins
 
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."HYS Enterprise
 
Behavioral Design Patterns
Behavioral Design PatternsBehavioral Design Patterns
Behavioral Design PatternsLidan Hifi
 
Petri Niemi Qt Advanced Part 2
Petri Niemi Qt Advanced Part 2Petri Niemi Qt Advanced Part 2
Petri Niemi Qt Advanced Part 2NokiaAppForum
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIJames Shvarts
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonfNataliya Patsovska
 
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq PermanaJetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq PermanaDicodingEvent
 
Larena3 0架构与关键技术
Larena3 0架构与关键技术Larena3 0架构与关键技术
Larena3 0架构与关键技术hik_lhz
 
5. state diagrams
5. state diagrams5. state diagrams
5. state diagramsAPU
 
5.state diagrams
5.state diagrams5.state diagrams
5.state diagramsAPU
 
GDSC NCU Flutter
GDSC NCU FlutterGDSC NCU Flutter
GDSC NCU FlutterNCUDSC
 
Java Design Patterns: The State Pattern
Java Design Patterns: The State PatternJava Design Patterns: The State Pattern
Java Design Patterns: The State PatternAntony Quinn
 
Rise of state_machines
Rise of state_machinesRise of state_machines
Rise of state_machinesMounir Boudraa
 
Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)Gabor Varadi
 

Ähnlich wie GameplayKit으로 상태표시 UI 쉽게 만들기 (20)

Unity3D Scripting: State Machine
Unity3D Scripting: State MachineUnity3D Scripting: State Machine
Unity3D Scripting: State Machine
 
Introduction to State Machines
Introduction to State MachinesIntroduction to State Machines
Introduction to State Machines
 
Flutter
FlutterFlutter
Flutter
 
An Introduction To CQRS
An Introduction To CQRSAn Introduction To CQRS
An Introduction To CQRS
 
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
 
Behavioral Design Patterns
Behavioral Design PatternsBehavioral Design Patterns
Behavioral Design Patterns
 
State Machine Framework
State Machine FrameworkState Machine Framework
State Machine Framework
 
Seminar State Chart1
Seminar State Chart1Seminar State Chart1
Seminar State Chart1
 
Petri Niemi Qt Advanced Part 2
Petri Niemi Qt Advanced Part 2Petri Niemi Qt Advanced Part 2
Petri Niemi Qt Advanced Part 2
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVI
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq PermanaJetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
 
Jar chapter 5_part_ii
Jar chapter 5_part_iiJar chapter 5_part_ii
Jar chapter 5_part_ii
 
Larena3 0架构与关键技术
Larena3 0架构与关键技术Larena3 0架构与关键技术
Larena3 0架构与关键技术
 
5. state diagrams
5. state diagrams5. state diagrams
5. state diagrams
 
5.state diagrams
5.state diagrams5.state diagrams
5.state diagrams
 
GDSC NCU Flutter
GDSC NCU FlutterGDSC NCU Flutter
GDSC NCU Flutter
 
Java Design Patterns: The State Pattern
Java Design Patterns: The State PatternJava Design Patterns: The State Pattern
Java Design Patterns: The State Pattern
 
Rise of state_machines
Rise of state_machinesRise of state_machines
Rise of state_machines
 
Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)Architecting Single Activity Applications (With or Without Fragments)
Architecting Single Activity Applications (With or Without Fragments)
 

Kürzlich hochgeladen

Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 

Kürzlich hochgeladen (20)

Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 

GameplayKit으로 상태표시 UI 쉽게 만들기

  • 1. GameplayKit 으로 상태표시 UI 쉽게 만들기 노수진 · 네이버웹툰 contact@soojin.ro 샘플코드 : https://github.com/nsoojin/VoiceControlSample-iOS
  • 4. 3가지 정의 요소 - 상태 (a list of states) - 변화의 조건 (transition) - 초기 상태 (initial state) 유한한 개수의 상태 중에서 한 번에 오로지 하나의 상태만을 가질 수 있고, 어떠한 사건에 의해 한 상태에서 다른 상태로 변화할 수 있다. Finite-State Machines 유한 상태 기계
  • 5. GameplayKit Randomization Entities and Components State Machines The Minmax Strategist Pathfinding Agents, Goals, Behaviors Rule Systems
  • 6. GameplayKit State Machines Use this architecture to untangle complex procedural code in your gameplay designs.
  • 7. State MachinesGameplayKit GKState - 상속 받아서, 오버라이드를 통해 상태별 동작과 전환(transition)의 조건을 정의 - State에 (1) 진입할 때, (2) 탈출할 때, 혹은 (3) State가 지속되는 동안 주기적으로 업데이트 GKStateMachine - [GKState] 를 파라미터로 넘겨서 생성 - 생성 후 초기 상태 지정
  • 8. UI 요구사항 분석 Core Animation Lottie animationView(Lottie) dotsContainerView(CoreAnimation)
  • 9. Core Animation internal final class DetectingState: VoiceState { private func bounce(_ dot: UIView) { let delayTime = 0.2 * Double(dot.tag - 1) let bounce = CAKeyframeAnimation(keyPath: “position.y”) bounce.beginTime = CACurrentMediaTime() + delayTime bounce.values = [0, -6, 0, 6, 0] bounce.keyTimes = [0, 0.25, 0.5, 0.75, 1.0] bounce.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut), CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn), CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut), CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)] bounce.duration = 1.0 bounce.isAdditive = true bounce.repeatCount = .infinity dot.layer.add(bounce, forKey: DetectingState.animationKey) } }
  • 10. Core Animation internal final class ListeningState: VoiceState { private func amplify(_ dot: UIView) { let noise = random(min: 0, max: 0.3) let animation = CASpringAnimation(keyPath: "bounds.size.height") animation.beginTime = CACurrentMediaTime() animation.toValue = dot.bounds.size.height * (regularized(magnitude) + noise) animation.initialVelocity = -15 animation.damping = 7 animation.stiffness = 750 animation.autoreverses = true animation.delegate = self animation.isRemovedOnCompletion = true dot.layer.add(animation, forKey: ListeningState.animationKey) } }
  • 11. Lottie internal final class ProcessingState: VoiceState { private func animateProcessing() { stateView.animationView.currentProgress = 0.16 stateView.animationView.loopMode = .loop stateView.animationView.play(fromProgress: 0.16, toProgress: 0.32) } } internal final class ReportingState: VoiceState { private func animateReporting() { stateView.animationView.currentProgress = 0.32 stateView.animationView.loopMode = .loop stateView.animationView.play(fromProgress: 0.32, toProgress: 0.52) } }
  • 12. GKState internal final class DetectingState: VoiceState { override func didEnter(from previousState: GKState?) { super.didEnter(from: previousState) animateBounce() } override func willExit(to nextState: GKState) { super.willExit(to: nextState) removeAnimation() } override func isValidNextState(_ stateClass: AnyClass) -> Bool { switch stateClass { case is AttendingState.Type, is ListeningState.Type: return true default: return false } } } (1) State 진입 시 (2) State 탈출 시 (3) Transition 조건
  • 13. internal class VoiceState: GKState { unowned let stateView: VoiceStateView init(statusView: VoiceStateView) { self.stateView = statusView } override func didEnter(from previousState: GKState?) { switch self { case is AttendingState, is ListeningState, is DetectingState: stateView.animationView.isHidden = true stateView.dotsContainerView.isHidden = false case is ProcessingState, is ReportingState: stateView.animationView.isHidden = false stateView.dotsContainerView.isHidden = true default: break } } } GKState Best Practice ⚠ 바로 GKState을 상속받지 말고 공통 Superclass State로 공유 자원 및 반복 로직을 관리
  • 14. internal class VoiceStateView: UIView { private lazy var stateMachine: GKStateMachine = { return GKStateMachine(states: [ AttendingState(statusView: self), DetectingState(statusView: self), ListeningState(statusView: self), ProcessingState(statusView: self), ReportingState(statusView: self) ]) }() override func didMoveToWindow() { state = .attending stateMachine.enter(AttendingState.self) } } GKStateMachine 진입할 수 있는 상태 초기 상태 지정 세팅 완료!
  • 15. internal final class VoiceStateView: UIView { @discardableResult func setState(_ state: State) -> Bool { let isNextStateValid = stateMachine.canEnterState(state.classType()) if isNextStateValid { self.state = state stateMachine.enter(state.classType()) } return isNextStateValid } } 상태 변경 extension VoiceControl: JarvisDelegate { func jarvis(_ jarvis: Jarvis, didChangeState state: JarvisState) { switch state { case .detecting: voiceAgentView?.transcription = listeningStateDescription voiceAgentView?.stateView?.setState(.detecting) ... 생략 ... } } }
  • 16. 전부 합치기 class VoiceStateView: UIView Jarvis(가칭) class VoiceControl: UIControl 👋
  • 17.
  • 18. 희망 사항 - 상태뷰는 항상 view hierarchy 최상단에 위치 - 도중에도 쉽게 dismiss / cancel - 어느 화면에나 쉽게 컨트롤 추가
  • 19.
  • 20. UIResponder var inputView: UIView? var inputAccessoryView: UIView?
  • 21. UIResponder var inputView: UIView? var inputAccessoryView: UIView?
  • 22. var inputAccessoryView: UIView? { get } inputView에 악세서리 뷰를 덧붙이고 싶을 때 사용한다. 인스턴스가 first responder가 되면 시스템이 이 뷰를 input view에 붙인 후 화면에 표시. inputView가 nil이어도 악세서리 뷰는 표시됨 ✨ 장점 - 애니메이션 : 네이티브 키보드처럼 show & hide - 레이아웃 : Safe Area 대응 용이 - 뷰 계층 : os가 별도 UIWindow로 관리 - Responder chain : becomeFirstResponder(), resignFirstResponder()
  • 23. resignFirstResponder()becomeFirstResponder() 마지막 총 정리 class VoiceControl: UIControl override var inputAccessoryView: UIView? { return voiceStateView } private var jarvis: Jarvis private var voiceStateView: VoiceStateView class VoiceStateView: UIView var stateMachine: GKStateMachine