Skip to content

Instantly share code, notes, and snippets.

@piemonte
Created April 14, 2023 03:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piemonte/eb4bc7daef5b6359ec32b24b034f0c42 to your computer and use it in GitHub Desktop.
Save piemonte/eb4bc7daef5b6359ec32b24b034f0c42 to your computer and use it in GitHub Desktop.
example for using the Position library bearing utility functions
//
// DirectionView.swift
//
// The MIT License (MIT)
//
// Copyright (c) 2020-present patrick piemonte (http://patrickpiemonte.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import UIKit
import Foundation
import CoreLocation.CLLocation
import Position
public final class DirectionView: UIView {
// MARK: - ivars
private lazy var _indicator: UIImageView = {
let view = UIImageView(image: UIImage(named: "direction_indicator")?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate))
view.translatesAutoresizingMaskIntoConstraints = false
view.tintColor = .black
return view
}()
private var _location: CLLocation?
private var _accuracyAnimator: UIViewPropertyAnimator?
// MARK: - object lifecycle
override public init(frame: CGRect) {
super.init(frame: frame)
setup()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
deinit {
LocationManager.shared.removeHeadingObserver(self)
}
}
extension DirectionView {
private func setup() {
addSubview(_indicator)
_accuracyAnimator = UIViewPropertyAnimator(duration: 0.15, curve: .easeInOut) {
self._indicator.alpha = 0.25
}
_indicator.alpha = 0
}
public func config(_ targetLocation: CLLocation) {
_location = targetLocation
LocationManager.shared.addHeadingObserver(self)
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseIn) {
self._indicator.alpha = 1
} completion: { _ in
}
}
}
// MARK: - LocationManagerHeadingObserver
extension DirectionView: LocationManagerHeadingObserver {
public func locationManager(_ locationManager: LocationManager, didUpdateHeading heading: CLHeading) {
guard let targetLocation = _location else { return }
guard let currentLocation = LocationContext.shared.lastLocation else { return // fade }
if heading.headingAccuracy >= 0,
let angle = currentLocation.bearingInRadians(toLocation: targetLocation, heading: heading) {
UIView.animate(withDuration: 0.25) { [weak self] in
guard let self = self else { return }
self._indicator.transform = CGAffineTransform(rotationAngle: angle)
}
} else {
// fade indicator (not accurate)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment