美文网首页
CoreLocation框架详细解析(十九) —— 基于UNLo

CoreLocation框架详细解析(十九) —— 基于UNLo

作者: 刀客传奇 | 来源:发表于2021-05-08 17:08 被阅读0次

    版本记录

    版本号 时间
    V1.0 2021.05.08 星期六

    前言

    很多的app都有定位功能,比如说滴滴,美团等,他们都需要获取客户所在的位置,并且根据位置推送不同的模块数据以及服务,可以说,定位方便了我们的生活,接下来这几篇我们就说一下定位框架CoreLocation。感兴趣的可以看我写的上面几篇。
    1. CoreLocation框架详细解析 —— 基本概览(一)
    2. CoreLocation框架详细解析 —— 选择定位服务的授权级别(二)
    3. CoreLocation框架详细解析 —— 确定定位服务的可用性(三)
    4. CoreLocation框架详细解析 —— 获取用户位置(四)
    5. CoreLocation框架详细解析 —— 监控用户与地理区域的距离(五)
    6. CoreLocation框架详细解析 —— 确定接近iBeacon(六)
    7. CoreLocation框架详细解析 —— 将iOS设备转换为iBeacon(七)
    8. CoreLocation框架详细解析 —— 获取指向和路线信息(八)
    9. CoreLocation框架详细解析 —— 在坐标和用户友好的地名之间转换(九)
    10. CoreLocation框架详细解析(十) —— 跟踪访问位置简单示例(一)
    11. CoreLocation框架详细解析(十一) —— 跟踪访问位置简单示例(二)
    12. CoreLocation框架详细解析(十二) —— 仿Runkeeper的简单实现(一)
    13. CoreLocation框架详细解析(十三) —— 仿Runkeeper的简单实现(二)
    14. CoreLocation框架详细解析(十四) —— 仿Runkeeper的简单实现(三)
    15. CoreLocation框架详细解析(十五) —— 仿Runkeeper的简单实现(四)
    16. CoreLocation框架详细解析(十六) —— 基于Core Location地理围栏的实现(一)
    17. CoreLocation框架详细解析(十七) —— 基于Core Location地理围栏的实现(二)
    18. CoreLocation框架详细解析(十八) —— 基于UNLocationNotificationTrigger的位置通知(一)

    源码

    1. Swift

    首先看下工程组织结构

    下面就是源码了

    1. AppMain.swift
    
    import SwiftUI
    
    @main
    struct AppMain: App {
      @StateObject private var locationManager = LocationManager()
    
      var body: some Scene {
        WindowGroup {
          ContentView()
            .environmentObject(locationManager)
        }
      }
    }
    
    2. ContentView.swift
    
    import SwiftUI
    
    struct ContentView: View {
      let takeOut = TakeOutStore()
      @EnvironmentObject private var locationManager: LocationManager
    
      var body: some View {
        NavigationView {
          MenuListView(takeOut: takeOut)
        }
        .navigationViewStyle(StackNavigationViewStyle())
        .alert(isPresented: $locationManager.didArriveAtTakeout) {
          Alert(
            title: Text("Check In"),
            message:
              Text("""
                You have arrived to collect your order.
                Do you want to check in?
                """),
            primaryButton: .default(Text("Yes")),
            secondaryButton: .default(Text("No"))
          )
        }
      }
    }
    
    struct ContentView_Previews: PreviewProvider {
      static var previews: some View {
        ContentView()
      }
    }
    
    3. MenuListView.swift
    
    import SwiftUI
    
    struct MenuListView: View {
      var takeOut: TakeOutStore
      var menuItems: [MenuItem] {
        return takeOut.menu
      }
    
      var body: some View {
        List(menuItems, id: \.id) { item in
          NavigationLink(
            destination: DetailView(menuItem: item)) {
            MenuListRow(menuItem: item)
          }
        }
        .navigationTitle(takeOut.title)
      }
    }
    
    struct MenuListView_Previews: PreviewProvider {
      static var previews: some View {
        MenuListView(takeOut: TakeOutStore())
      }
    }
    
    4. MenuListRow.swift
    
    import SwiftUI
    
    struct MenuListRow: View {
      var menuItem: MenuItem
    
      var body: some View {
        HStack {
          Image(menuItem.imageName)
            .resizable()
            .frame(width: 50, height: 50)
          Text(menuItem.name)
    
          Spacer()
        }
      }
    }
    
    struct MenuListRow_Previews: PreviewProvider {
      static var previews: some View {
        MenuListRow(menuItem: menuItems[0])
          .previewLayout(.fixed(width: 300, height: 50))
      }
    }
    
    5. DetailView.swift
    
    import SwiftUI
    
    struct DetailView: View {
      @EnvironmentObject private var locationManager: LocationManager
      @State private var orderPlaced = false
      let menuItem: MenuItem
      var price: String {
        return "$" + String(format: "%.2f", menuItem.price)
      }
    
      var body: some View {
        VStack {
          Image(menuItem.imageName)
            .resizable()
            .frame(maxWidth: 300, maxHeight: 600)
            .aspectRatio(contentMode: .fit)
          Text(menuItem.name)
            .font(.headline)
          Divider()
          Text("Price: \(price)")
            .font(.subheadline)
            .padding(15)
          Button(action: placeOrder) {
            Text("Place Order: \(price)")
              .foregroundColor(.white)
              .frame(minWidth: 100, maxWidth: .infinity)
              .frame(height: 45)
          }
          .background(Color("rw-green"))
          .cornerRadius(3.0)
        }
        .alert(isPresented: $orderPlaced) {
          Alert(
            title: Text("Food Ordered"),
            message:
              Text("""
                Your food has been ordered.
                Would you like to be notified on arrival?
                """),
            primaryButton: .default(Text("Yes")) {
              requestNotification()
            },
            secondaryButton: .default(Text("No"))
          )
        }
        .padding()
        .navigationBarTitle(Text(menuItem.name), displayMode: .inline)
      }
    
      func placeOrder() {
        orderPlaced = true
      }
    
      func requestNotification() {
        locationManager.validateLocationAuthorizationStatus()
      }
    }
    
    struct DetailView_Previews: PreviewProvider {
      static var previews: some View {
        DetailView(menuItem: menuItems[0])
      }
    }
    
    6. SimulatedLocations.gpx
    
    <?xml version="1.0"?>
    <gpx version="1.1" creator="Xcode">
      <wpt lat="37.422155" lon="-122.134751">
        <name>Apple Park</name>
        <time>2021-01-23T14:00:00Z</time>
      </wpt>
      <wpt lat="37.33182000" lon="-122.03118000">
        <name>Apple Campus</name>
        <time>2021-01-23T14:00:05Z</time>
      </wpt>
    </gpx>
    
    7. LocationManager.swift
    
    import CoreLocation
    import UserNotifications
    
    class LocationManager: NSObject, ObservableObject {
      let location = CLLocationCoordinate2D(latitude: 37.33182, longitude: -122.03118)
      let notificationCenter = UNUserNotificationCenter.current()
      lazy var storeRegion = makeStoreRegion()
      @Published var didArriveAtTakeout = false
      // 1
      lazy var locationManager = makeLocationManager()
      // 2
      private func makeLocationManager() -> CLLocationManager {
        // 3
        let manager = CLLocationManager()
        manager.allowsBackgroundLocationUpdates = true
        // 4
        return manager
      }
    
      // 1
      private func makeStoreRegion() -> CLCircularRegion {
        // 2
        let region = CLCircularRegion(
          center: location,
          radius: 2,
          identifier: UUID().uuidString)
        // 3
        region.notifyOnEntry = true
        // 4
        return region
      }
    
      // 1
      func validateLocationAuthorizationStatus() {
        // 2
        switch locationManager.authorizationStatus {
        // 3
        case .notDetermined, .denied, .restricted:
          // 4
          print("Location Services Not Authorized")
          locationManager.requestWhenInUseAuthorization()
          requestNotificationAuthorization()
    
        // 5
        case .authorizedWhenInUse, .authorizedAlways:
          // 6
          print("Location Services Authorized")
          requestNotificationAuthorization()
    
        default:
          break
        }
      }
    
      // 1
      private func requestNotificationAuthorization() {
        // 2
        let options: UNAuthorizationOptions = [.sound, .alert]
        // 3
        notificationCenter
          .requestAuthorization(options: options) { [weak self] result, _ in
            // 4
            print("Auth Request result: \(result)")
            if result {
              self?.registerNotification()
            }
          }
      }
    
      // 1
      private func registerNotification() {
        // 2
        let notificationContent = UNMutableNotificationContent()
        notificationContent.title = "Welcome to Swifty TakeOut"
        notificationContent.body = "Your order will be ready shortly."
        notificationContent.sound = .default
    
        // 3
        let trigger = UNLocationNotificationTrigger(region: storeRegion, repeats: false)
    
        // 4
        let request = UNNotificationRequest(
          identifier: UUID().uuidString,
          content: notificationContent,
          trigger: trigger)
    
        // 5
        notificationCenter
          .add(request) { error in
            if error != nil {
              print("Error: \(String(describing: error))")
            }
          }
      }
    
      // 1
      override init() {
        super.init()
        // 2
        notificationCenter.delegate = self
      }
    }
    extension LocationManager: UNUserNotificationCenterDelegate {
      // 1
      func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
      ) {
        // 2
        print("Received Notification")
        didArriveAtTakeout = true
        // 3
        completionHandler()
      }
    
      // 4
      func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler:
          @escaping (UNNotificationPresentationOptions) -> Void
      ) {
        // 5
        print("Received Notification in Foreground")
        didArriveAtTakeout = true
        // 6
        completionHandler(.sound)
      }
    }
    
    8. TakeOutStore.swift
    
    import Foundation
    
    struct TakeOutStore {
      let menu = menuItems
      var title = "Swifty TakeOut"
    }
    
    9. MenuItem.swift
    
    import Foundation
    
    struct MenuItem {
      let id = UUID()
      var name: String
      var imageName: String
      var price: Double
    }
    
    // MARK: - Menu Items
    let menuItems: [MenuItem] = [
      MenuItem(name: "Margherita Pizza SE", imageName: "cheese-pizza-small", price: 7.00),
      MenuItem(name: "Margherita Pizza Max", imageName: "cheese-pizza", price: 10.00),
      MenuItem(name: "Margherita Pizza Max Pro", imageName: "cheese-pizza", price: 12.00),
      MenuItem(name: "Chicken Pizza SE", imageName: "chicken-pizza-small", price: 8.00),
      MenuItem(name: "Chicken Pizza Max", imageName: "chicken-pizza", price: 11.00),
      MenuItem(name: "Chicken Pizza Max Pro", imageName: "chicken-pizza", price: 14.00),
      MenuItem(name: "Pepperoni Pizza SE", imageName: "pep-pizza-small", price: 7.00),
      MenuItem(name: "Pepperoni Pizza Max", imageName: "pep-pizza", price: 11.00),
      MenuItem(name: "Pepperoni Pizza Max Pro", imageName: "pep-pizza", price: 14.00),
      MenuItem(name: "Swifty Shake Series 6", imageName: "shake", price: 3.50),
      MenuItem(name: "Swifty Shake SE", imageName: "shake", price: 2.00),
      MenuItem(name: "Swifty Shake Series 3", imageName: "shake", price: 2.75)
    ]
    

    后记

    本篇主要讲述了基于UNLocationNotificationTrigger的位置通知,感兴趣的给个赞或者关注~~~

    相关文章

      网友评论

          本文标题:CoreLocation框架详细解析(十九) —— 基于UNLo

          本文链接:https://www.haomeiwen.com/subject/jkoudltx.html