EEYatHo 앱 깎는 이야기

Swift ) HapticEngine 진동. 원하는 패턴. 무한반복 - EEYatHo iOS 본문

iOS, Swift/Feature

Swift ) HapticEngine 진동. 원하는 패턴. 무한반복 - EEYatHo iOS

EEYatHo 2022. 10. 28. 16:02
반응형

 

 

CHHapticEngine


iOS 에서 제공하는 CHHapticEngine 을 이용하여 다양한 진동을 구현할 수 있다.

 

보다 자세한 설명을 원한다면 공식 링크에서 확인하기.

CHHapticEngine 링크

 

큰 개념은, HapticEngine 에 진동 Pattern 을 넣어서 Player 를 생성한다.

Player 를 start 및 stop 한다.

 

 

 

CHHapticPattern


HapticPattern 에는 지속시간과 세기가 있으며,

세기에는 강도(hapticIntensity) 와 날카로움(hapticSharpness) 이 있다.

 

강도는 클수록 묵직한 느낌이다. 내 생각엔 진폭을 담당한다.

날카로움은 클수록 따가운(?) 느낌이다. 내 생각엔 진동수를 담당한다.

 

애플에서 제공하는 예시 프로젝트를 실행해보면 직접 느껴볼 수 있다.

애플의 공식 문서 with 예시 프로젝트

 

자세한 설명은 아래 공식 문서에서 확인하기.

CHHapticPattern 링크

 

 

 

 

SingleTon 예시


지속 시간(durations) 과, 세기(powers) 의 배열을 넣어서 진동을 켜고 끄는 싱글톤이다.

VibrationManager.shared.playHaptic(durations: [1.0, 2.0], powers: [0.5, 1.0])
// 중간 강도로 1초, 강한 강도로 2초 진동하는 패턴을 무한 반복한다.

 

강도를 이용해서 진동의 세기를 조절했으며,

날카로움은 내가 느꼈을 때 가장 강하게 느껴지던 0.6 으로 정했다.

 

stop 을 호출하기 전 까지, 무한반복 ( loopEnable = true ) 이다.

 

 

class VibrationManager {

    static let shared = VibrationManager()
    
    private let hapticEngine: CHHapticEngine
    private var hapticAdvancedPlayer: CHHapticAdvancedPatternPlayer? = nil /// 엔진이 패턴가지고 만드는 플레이어
    
    init?() {
        let hapticCapability = CHHapticEngine.capabilitiesForHardware()
        
        guard hapticCapability.supportsHaptics else {
            print("Haptic engine Creation Error: Not Support")
            return nil
        }
        
        do {
            hapticEngine = try CHHapticEngine()
        } catch let error {
            print("Haptic engine Creation Error: \(error)")
            return nil
        }
    }


    func stopHapric() {
        do {
            print(" 0. 진동 끄기")
            try hapticAdvancedPlayer?.stop(atTime: 0)
        } catch {
            print("Failed to stopHapric: \(error)")
        }
    }
    
    
    func playHaptic(durations: [Double], powers: [Float]) {
        do {
            print(" 0. 전에 있던 진동 끄기")
            try hapticAdvancedPlayer?.stop(atTime: 0)
            
            print(" 1. 패턴만들기")
            let pattern = try makePattern(durations: durations, powers: powers)
            
            print(" 2. 엔진시작, 플레이어 만들기")
            try hapticEngine.start()
            hapticAdvancedPlayer = try hapticEngine.makeAdvancedPlayer(with: pattern)
            hapticAdvancedPlayer?.loopEnabled = true
            hapticAdvancedPlayer?.playbackRate = 1.0
            
            print(" 3. 플레이어 시작")
            try hapticAdvancedPlayer?.start(atTime: 0)
        } catch {
            print("Failed to playHaptic: \(error)")
        }
    }
    
    /// duration 단위 : second(초)
    /// power 단위 : 0.0 ~ 1.0
    private func makePattern(durations: [Double], powers: [Float]) throws -> CHHapticPattern {
        
        var events: [CHHapticEvent] = []
        var relativeTime = 0.0
        
        durations.enumerated().forEach {
            let duration = $0.element
            let power = powers[$0.offset]
            
            let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: power)
            let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.6)
            
            let params = [intensity, sharpness]
    
            let event = CHHapticEvent(eventType: .hapticContinuous, parameters: params, relativeTime: relativeTime, duration: duration)
            relativeTime += duration
            events.append(event)
        }
        
        return try CHHapticPattern(events: events, parameters: [])
    }
    
}
Comments