更换屏幕时崩溃 - iBeacon iOS

时间:2017-03-16 07:23:46

标签: ios swift ibeacon

在添加iBeacon代码以找到两个设备之间的距离后,导航到其他屏幕(onBackButton)时出现错误。

以下是我的示例代码:

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

任何帮助都将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

这清楚地表明,即使您是stopAdvertising BLE,也不会停止宣传数据,因此当下一个广告广播时,它会因为无法找到delegate而崩溃。

所以我的建议是在deinit方法中停止所有内容。因为当我们回到上一个屏幕时,我们应deinit分配所有对象,以便应用程序不会崩溃。

确保在该类中调用deinit函数。

答案 1 :(得分:0)

CLLocationManager委托分配(无主(不安全))并非弱。你必须在你的deinit中将委托设置为nil。