BLE iOS9 的 Swift 后台模式

Posted

技术标签:

【中文标题】BLE iOS9 的 Swift 后台模式【英文标题】:Swift background mode for BLE iOS9 【发布时间】:2016-06-02 04:27:36 【问题描述】:

我想改进 MPCRevisited 项目,它是使用多点方法的聊天应用程序。我正在使用 BLE 将一台设备连接到另一台设备(iPad 和 iPod)并发送和接收数据。但是,当我在一台设备上按主页按钮进入后台模式时,5 秒后,我无法发送或接收数据。

此处有图片说明

我已经在后台模式下检查了所有内容,但它仍然无法正常工作。

import UIKit
import MultipeerConnectivity

class ParkBenchTimer 

    let startTime:CFAbsoluteTime
    var endTime:CFAbsoluteTime?

    init() 
        startTime = CFAbsoluteTimeGetCurrent()
    

    func stop() -> CFAbsoluteTime 
        endTime = CFAbsoluteTimeGetCurrent()

        return duration!
    

    var duration:CFAbsoluteTime? 
        if let endTime = endTime 
            return endTime - startTime
         else 
            return nil
        
    




class ChatViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource 

    @IBOutlet weak var chatTextField: UITextField!

    @IBOutlet weak var chatTableView: UITableView!

    var messagesArray: [[String : String]] = []

    let mpcManager = MPCManager.sharedInstance


    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.chatTableView.delegate = self
        self.chatTableView.dataSource = self

        self.chatTableView.estimatedRowHeight = 60.0
        self.chatTableView.rowHeight = UITableViewAutomaticDimension

        self.chatTextField.delegate = self

        self.mpcManager.messageRecievedDelegate = self
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    
    */


    // MARK: IBAction method implementation

    @IBAction func endChat(sender: AnyObject) 
        let messageDictionary: [String: String] = ["message": "_end_chat_"]
        if self.mpcManager.sendData(dictionaryWithData: messageDictionary, toPeer: self.mpcManager.session.connectedPeers[0] as MCPeerID)
            self.dismissViewControllerAnimated(true, completion:  () -> Void in
                self.mpcManager.session.disconnect()
            )
        
    


    // MARK: UITableView related method implementation

    func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return 1
    


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.messagesArray.count
    


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

        guard let cell = tableView.dequeueReusableCellWithIdentifier("idCell") else 
            assert(true)
            return UITableViewCell()
        

        guard let currentMessage = self.messagesArray[safe: indexPath.row] else 
            print(" ")
            assert(true)
            return UITableViewCell()
        

        if let sender = currentMessage["sender"] 
            var senderLabelText: String
            var senderColor: UIColor

            if sender == "self" 

                senderLabelText = "I said:"
                senderColor = UIColor.purpleColor()

             else 

                senderLabelText = sender + " said:"
                senderColor = UIColor.orangeColor()

            

            cell.detailTextLabel?.text = senderLabelText
            cell.detailTextLabel?.textColor = senderColor
        

        if let message = currentMessage["message"] 
            cell.textLabel?.text = message
        

        return cell
    



    // MARK: UITextFieldDelegate method implementation

    func textFieldShouldReturn(textField: UITextField) -> Bool 
        textField.resignFirstResponder()

        guard let textFieldText = textField.text else 
            assert(true)
            return false
        


        let messageDictionary: [String: String] = ["message": textFieldText]

        guard let connectedPeer = self.mpcManager.session.connectedPeers[safe: 0] else 

            print(" ")
            assert(true)
            return false
        

        if self.mpcManager.sendData(dictionaryWithData: messageDictionary, toPeer: connectedPeer) 

            let dictionary = ["sender": "self", "message": textFieldText]
            self.messagesArray.append(dictionary)

            self.updateTableview()

         else 

            print("Could not send data")

        

        textField.text = ""

        return true
    


    // MARK: Custom method implementation

    func updateTableview()
        chatTableView.reloadData()

        if self.chatTableView.contentSize.height > self.chatTableView.frame.size.height 

            let indexPathToScrollTo = NSIndexPath(forRow: messagesArray.count - 1, inSection: 0)

            self.chatTableView.scrollToRowAtIndexPath(indexPathToScrollTo, atScrollPosition: .Bottom, animated: true)
        
    




extension ChatViewController : MPCManagerRecievedMessageDelegate 
    func managerRecievedData(data:NSData ,fromPeer:MCPeerID) 
        // Convert the data (NSData) into a Dictionary object.
        let dataDictionary = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [String : String]


        // Check if there's an entry with the "message" key.
        if let message = dataDictionary["message"] 
            // Make sure that the message is other than "_end_chat_".
            if message != "_end_chat_"

                // Create a new dictionary and set the sender and the received message to it.
                let messageDictionary: [String: String] = ["sender": fromPeer.displayName, "message": message]

                // Add this dictionary to the messagesArray array.
                messagesArray.append(messageDictionary)

                // Reload the tableview data and scroll to the bottom using the main thread.
                self.updateTableview()

             else 


            
        

    

    func managerDidRecievedMessage(message: String, fromPeer: MCPeerID) 
        // Create a new dictionary and set the sender and the received message to it.
        //let messageDictionary: [String: String] = ["sender": fromPeer.displayName, "message": message]

        // Add this dictionary to the messagesArray array.
        //messagesArray.append(messageDictionary)

        // Reload the tableview data and scroll to the bottom using the main thread.
        //self.updateTableview()
    

    func managerDidEndChat(fromPeer:MCPeerID) 

        // In this case an "_end_chat_" message was received.
        // Show an alert view to the user.
        let alert = UIAlertController(title: "", message: "\(fromPeer.displayName) ended this chat.", preferredStyle: UIAlertControllerStyle.Alert)

        let doneAction: UIAlertAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.Default)  (alertAction) -> Void in
            self.mpcManager.session.disconnect()
            self.dismissViewControllerAnimated(true, completion: nil)
        

        alert.addAction(doneAction)

        self.presentViewController(alert, animated: true, completion: nil)

    

这是我的代码。

如果有人知道这个问题,请帮助我。我想做的是一个设备继续发送消息,另一个设备来回成为后台和前台。

谢谢。

【问题讨论】:

【参考方案1】:

查看其他一些 *** 帖子(here 和 here),Multipeer Connectivity Framework 似乎不是为在后台运行而构建的,您的功能将在几分钟后消失。

蓝牙在后台运行,具有您检查的功能,但您必须创建自己的消息传递平台;尽管 Multipeer 部分依赖于蓝牙,但这些功能是独立的实体。

【讨论】:

以上是关于BLE iOS9 的 Swift 后台模式的主要内容,如果未能解决你的问题,请参考以下文章

Cordova:在后台模式下扫描 iBeacons / BLE(iOS 和 Android)

iOS iOS9.0 的CoreLocation定位

在 iOS 后台实现 BLE 扫描

iOS 在后台模式下从广告中省略制造商数据

NSTimer 在后台模式下使用 locationManager 委托(“作弊方式”)SWIFT

后台模式下的多点连接