2017-03-16 64 views
0

我在添加我的iBeacon代碼以找到兩個設備之間的距離後導航到其他屏幕(onBackButton)時出現錯誤。更換屏幕時發生崩潰 - iBeacon iOS

這裏是我的示例代碼:

import Foundation 
import UIKit 
import SlideMenuControllerSwift 
import CoreLocation 
import QuartzCore 
import CoreLocation 
import CoreBluetooth 

class PokemonViewController: UIViewController , CLLocationManagerDelegate, CBPeripheralManagerDelegate{ 

    var beaconRegion: CLBeaconRegion! 
    var bluetoothPeripheralManager: CBPeripheralManager! 
    var isBroadcasting = false 
    var dataDictionary = NSDictionary() 
    var isSearchingForBeacons = false 
    var lastFoundBeacon: CLBeacon! = CLBeacon() 
    var lastProximity: CLProximity! = CLProximity.unknown 

    var locationManager: CLLocationManager! 

    var my_uuid : String = "" 
    var other_uuid : String = "" 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.title = "Find Me" 
     var image = UIImage(named: "arrow") 
     image = image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal) 

     self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: Shared().imageRotatedByDegrees(oldImage: image!, deg: 180), style: UIBarButtonItemStyle.plain, target: self, action: #selector(onBackButton)) 
     navigationController?.navigationBar.barTintColor = UIStyle().hexStringToUIColor("#e2041a") 
    } 

    override func viewDidAppear(_ animated: Bool) { 
     self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "Avenir Next", size: 20)!] 
     Pokemon.isPokemon = true 
     self.bluetoothPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil) 
    } 

    override func viewWillAppear(_ animated: Bool) { 
     super.viewWillAppear(animated) 

     self.slideMenuController()?.removeLeftGestures() 
     self.slideMenuController()?.removeRightGestures() 

     //self.setNavigationBarItem() 

     let nav = self.navigationController?.navigationBar 
     nav?.barStyle = UIBarStyle.black 
     nav?.tintColor = UIColor.white 
     nav?.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white] 

     let url = "\(Webcall().url)getuserdetails?user_id=\(userIdInvite)&token=\(UserDefaults.standard.object(forKey: "user_token") as! String)" 
     getUserDataRequest(url) 
    } 

    override func viewDidDisappear(_ animated: Bool) { 
    } 

    override func viewWillDisappear(_ animated: Bool) { 
     locationManager.stopMonitoring(for: beaconRegion) 
     locationManager.stopRangingBeacons(in: beaconRegion) 
     locationManager.stopUpdatingLocation() 

     isSearchingForBeacons = !isSearchingForBeacons 
     bluetoothPeripheralManager.stopAdvertising() 
     isBroadcasting = false 
    } 

    func onBackButton() { 
     let storyboard = UIStoryboard(name: "Main", bundle: nil) 
     let resultViewController = storyboard.instantiateViewController(withIdentifier: "RadarViewController") as! RadarViewController 
     _ = navigationController?.popViewController(animated: true) 
    } 
} 

extension PokemonViewController { 
    func getUserDataRequest(_ url: String) { 

     var url = url 
     print(url) 
     url = url.replacingOccurrences(of: "+", with: "%2B", options: .literal, range: nil) 

     //present(Validation().waitAlert(), animated: true, completion: nil) 
     Shared().showLoaderGif(view: self.view) 

     _ = URLSession.shared 

     let urlPath = URL(string: url) 
     let request = NSMutableURLRequest(url: urlPath!) 
     request.timeoutInterval = 60 
     request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData 
     request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") 
     request.httpMethod = "POST" 

     let dataTask = URLSession.shared.dataTask(with: request as URLRequest,completionHandler: {(data, response, error) -> Void in 

      if((error) != nil) { 
      }else { 

       let statusCode = (response as! HTTPURLResponse).allHeaderFields 
       _ = statusCode["Connection"]! 


       _ = NSString(data: data!, encoding:String.Encoding.utf8.rawValue) 
       let _: NSError? 
       let jsonResult: AnyObject = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 
       print(jsonResult) 
       let flag = jsonResult["flag"] as! String 
       let message = jsonResult["message"] as! String 
       DispatchQueue.main.async { 
        Shared().hideLoaderGif(view: self.view) 
        if flag == "1" { 
         let data = jsonResult["data"] as? [String: AnyObject] 
         self.my_uuid = data?["my_udid"]! as! String 
         self.other_uuid = data?["usr_udid"]! as! String 

         self.switchBroadcastingState() 

        }else { 
         let uiAlert = UIAlertController(title: "Hello \(UserDefaults.standard.object(forKey: "user_name") as! String)", message: message , preferredStyle:.alert) 
         self.present(uiAlert, animated: true, completion: nil) 

         uiAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { action in})) 
        } 
       } 

      } 
     }) 
     dataTask.resume() 
    } 
} 

//iBeacon 
extension PokemonViewController { 
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { 
     print("State -> ->", peripheral.state) 
     switch peripheral.state { 
     case .poweredOff: 
      if isBroadcasting { 
       switchBroadcastingState() 
       print("Power Off ->->") 
      } 
     case .poweredOn: 
      print("Power On ->->") 
     case .resetting: 
      print("resetting ->->") 
     case .unauthorized: 
      print("unauthorized ->->") 
     case .unsupported: 
      print("unsupported ->->") 
     default: 
      print("default ->->") 
     } 
    } 

    func switchBroadcastingState() { 
     if !isBroadcasting { 
      if bluetoothPeripheralManager.state == .poweredOn { 
       print("My UUID: \(self.my_uuid)") 
       print("Other UUID: \(self.other_uuid)") 

       /* It prints 
       My UUID: 1D2E9DF1-7A0E-4299-A755-AE11EBBC2C72 
       Other UUID: 58B2E595-F4CC-4BAD-8817-F09CD15DB94C*/ 

       let myUuid = UUID(uuidString: "\(self.my_uuid)") 
       let major: CLBeaconMajorValue = UInt16(Int(1)) 
       let minor: CLBeaconMinorValue = UInt16(Int(1)) 
       beaconRegion = CLBeaconRegion(proximityUUID: myUuid!, major: major, minor: minor, identifier: "com.iMeetUp") 

       dataDictionary = beaconRegion.peripheralData(withMeasuredPower: nil) 
       bluetoothPeripheralManager.startAdvertising((dataDictionary as! [String : Any])) 

       isBroadcasting = true 
      } 
     } else { 
      bluetoothPeripheralManager.stopAdvertising() 
      isBroadcasting = false 
     } 


     self.locationManager = CLLocationManager() 
     self.locationManager.delegate = self 

     let otherUuid = UUID(uuidString: "\(self.other_uuid)") 
     beaconRegion = CLBeaconRegion(proximityUUID: otherUuid!, identifier: "com.iMeetUp") 

     beaconRegion.notifyOnEntry = true 
     beaconRegion.notifyOnExit = true 
     beaconRegion.notifyEntryStateOnDisplay = true 
     if !isSearchingForBeacons { 
      locationManager.requestAlwaysAuthorization() 
      locationManager.startMonitoring(for: beaconRegion) 
      locationManager.startUpdatingLocation() 
     } else { 
      locationManager.stopMonitoring(for: beaconRegion) 
      locationManager.stopRangingBeacons(in: beaconRegion) 
      locationManager.stopUpdatingLocation() 
     } 
     isSearchingForBeacons = !isSearchingForBeacons 
    } 

    func locationManager(_ manager: CLLocationManager!, didStartMonitoringFor region: CLRegion) { 
     print("Called Called Called 1 -> -> ->") 
     locationManager.requestState(for: region) 
    } 

    func locationManager(_ manager: CLLocationManager!, didDetermineState state: CLRegionState, for region: CLRegion) { 
     if state == CLRegionState.inside { 
      print("Called Called Called 2 -> -> ->") 
      locationManager.startRangingBeacons(in: beaconRegion) 
     } 
     else { 
      print("Called Called Called 3 -> -> ->") 
      locationManager.stopRangingBeacons(in: beaconRegion) 
     } 
    } 

    func locationManager(_ manager: CLLocationManager!, didEnterRegion region: CLRegion) { 
    } 

    func locationManager(_ manager: CLLocationManager!, didExitRegion region: CLRegion) { 
    } 

    func locationManager(_ manager: CLLocationManager!, didFailWithError error: Error) { 
     print("Error -> -> didFailWithError : ", error) 
    } 
    func locationManager(_ manager: CLLocationManager!, monitoringDidFailFor region: CLRegion?, withError error: Error) { 
     print("Error -> -> monitoringDidFailFor : ", error) 
    } 

    func locationManager(_ manager: CLLocationManager!, rangingBeaconsDidFailFor region: CLBeaconRegion, withError error: Error) { 
     print("Error -> -> rangingBeaconsDidFailFor : ", error) 
    } 

    func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon]!, in region: CLBeaconRegion) { 
     print("founddddddd") 
     var shouldHideBeaconDetails = true 

     if let foundBeacons = beacons { 
      if foundBeacons.count > 0 { 
       if let closestBeacon = foundBeacons[0] as? CLBeacon { 
        print("Found Device: ", foundBeacons) 
        if closestBeacon != lastFoundBeacon || lastProximity != closestBeacon.proximity { 
         //lastFoundBeacon = closestBeacon as CLBeacon 
         //lastProximity = closestBeacon.proximity 

         var proximityMessage: String! 
         print("Distance M: ", closestBeacon.accuracy) 
         switch closestBeacon.proximity { 
         case CLProximity.immediate: 
          proximityMessage = "Distance: \(String(format: "%.2f", closestBeacon.accuracy))m" 

         case CLProximity.near: 
          proximityMessage = "Distance: \(String(format: "%.2f", closestBeacon.accuracy))m" 

         case CLProximity.far: 
          proximityMessage = "Distance: \(String(format: "%.2f", closestBeacon.accuracy))m" 

         default: 
          proximityMessage = "Not Found!" 
         } 

         shouldHideBeaconDetails = false 
         //lblBeaconDetails.text = "Beacon Details:\nMajor = " + String(closestBeacon.major.int32Value) + "\nMinor = " + String(closestBeacon.minor.int32Value) + "\nDistance: " + proximityMessage + "\nDistance (m): \(String(format: "%.2f", closestBeacon.accuracy))" 

        } 
       } 
      } 
     } 
    } 
} 

下面是我在Xcode中得到了錯誤的屏幕截圖: enter image description here

任何幫助將得到高度讚賞。

+0

你在控制檯上得到了什麼錯誤? – iDeveloper

+0

什麼都沒有。它直接進入我的AppDelegate.swift文件。 – Dhruv

回答

0

這清楚地表明,即使你是stopAdvertising BLE,它也不會停止廣告數據,因此當下次廣告廣播時,它會因爲找不到delegate而崩潰。

所以我的建議是停止一切在deinit方法。因爲當我們回到上一個屏幕時,我們應該爲deinit全部分配對象,以便應用程序不會崩潰。

確保它在該類中調用deinit函數。

+0

您可以詳細說明一下,因爲我已將'viewWillDisappear'方法的代碼移至'deinit'。但它仍然不起作用。 – Dhruv

0

CLLocationManager委託被分配(無主(不安全))不弱。您必須將代表設置爲零。

+0

對不起,但它不工作。 – Dhruv