2017-01-06 2 views
0

Ich habe eine App, die ein UILabel hat, dass ich gerne von einer anderen Swift-Klasse aktualisiert würde? Die Klasse ist eine Serviceklasse und hat keine Beziehung zum View-Controller mit dem UILabel, aber ich möchte trotzdem, dass diese Serviceklasse das Label aktualisieren kann.Update UILabel von einer anderen Klasse (ohne Bezug zum View-Controller)

Ich glaube, dass this Antwort war, was ich brauchte, aber es funktioniert nicht für Swift 3 und der Text, den die Beschriftung ändert, ist hardcodiert, was nicht das ist, was ich auch wollte. Ich konnte nichts anderes dazu finden.

BTService.swift:

import Foundation 
import CoreBluetooth 

let BLEServiceUUID = CBUUID(string: "025A7775-49AA-42BD-BBDB-E2AE77782966") 
let PositionCharUUID = CBUUID(string: "A9CD2F86-8661-4EB1-B132-367A3434BC90") //RX let 
let WriteCharUUID = CBUUID(string: "F38A2C23-BC54-40FC-BED0-60EDDA139F47") //TX let F38A2C23-BC54-40FC-BED0-60EDDA139F47 
let BLEServiceChangedStatusNotification = "kBLEServiceChangedStatusNotification" 
class BTService: NSObject, CBPeripheralDelegate { 
    var peripheral: CBPeripheral? 
    var positionCharacteristic: CBCharacteristic? 
    var writeCharacteristic: CBCharacteristic? 


    init(initWithPeripheral peripheral: CBPeripheral) { 
     super.init() 

     self.peripheral = peripheral 
     self.peripheral?.delegate = self 
    } 

    deinit{ 
     self.reset() 
    } 

    func startDiscoveringServices() { 
     self.peripheral?.discoverServices([BLEServiceUUID]) 
    } 

    func reset() { 
     if peripheral != nil { 
      peripheral = nil 
     } 
     // Deallocating therefore send notification 
     self.sendBTServiceNotificationWithIsBluetoothConnected(false) 
    } 


    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { 
     let uuidsForBTService: [CBUUID] = [PositionCharUUID] 
     let uuidsForBTService1: [CBUUID] = [WriteCharUUID] 
     if (peripheral != self.peripheral) { // Wrong Peripheral 
      return 
     } 
     if (error != nil) { 
      return 
     } 

     if ((peripheral.services == nil) || (peripheral.services?.count == 0)) { 
      // No Services 
      return 
     } 

     for service in peripheral.services! { 
      if service.uuid == BLEServiceUUID { 
       peripheral.discoverCharacteristics(uuidsForBTService, for: service 
       ) 
       peripheral.discoverCharacteristics(uuidsForBTService1, for: service) 
      } } 
    } 


    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { 
     if (peripheral != self.peripheral) { // Wrong Peripheral 
      return } 
     if (error != nil) { 
      return 
     } 

     for characteristic in service.characteristics! { if characteristic.uuid == PositionCharUUID { 
      self.positionCharacteristic = (characteristic) 
      peripheral.setNotifyValue(true, for: characteristic) 

      self.sendBTServiceNotificationWithIsBluetoothConnected(true) 

     } 
     else if characteristic.uuid == WriteCharUUID { 
      self.writeCharacteristic = (characteristic) 
      peripheral.setNotifyValue(true, for: characteristic) 

      self.sendBTServiceNotificationWithIsBluetoothConnected(true) 

      } 
     } 
    } 

    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){ 

     let it = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue) 

     if(it != nil){ 
      print("Val: \(it)") //Stackoverflow: This is what needs to be sent to the ViewController to be updated!!! 
     } 


    } 



    func writePosition(position: UInt8) { 
     if self.writeCharacteristic == nil { 
      return 
     } 

     var positionValue = position 
     let data = NSData(bytes: &positionValue, length: MemoryLayout<UInt8>.size) 
     self.peripheral?.writeValue(data as Data, for: self.writeCharacteristic!, type: CBCharacteristicWriteType.withResponse) 
    } 


    func readPosition() -> NSString? { 
     if self.positionCharacteristic == nil { 
      return nil } 
     self.peripheral?.readValue(for: self.positionCharacteristic!) 
     if ((self.positionCharacteristic?.value) != nil) { 
      print(self.positionCharacteristic!.value!) 
      return NSString(data: self.positionCharacteristic!.value!, encoding: 
       String.Encoding.utf8.rawValue) } 

     return nil 
    } 

    func sendBTServiceNotificationWithIsBluetoothConnected(_ isBluetoothConnected: Bool) { 
     let connectionDetails = ["isConnected": isBluetoothConnected] 
     NotificationCenter.default.post(name: Notification.Name(rawValue: BLEServiceChangedStatusNotification), object: self, userInfo: connectionDetails) 
    } 




} 

Der Viewcontroller:

import UIKit 
import AVFoundation 


class ViewController: UIViewController { 

    @IBOutlet weak var imgBluetoothStatus: UIImageView! 
    @IBOutlet weak var positionSlider: UISlider! 
    @IBOutlet weak var BottomLabel: UILabel! 




    var timerTXDelay: Timer? 
    var allowTX = true 
    var lastPosition: UInt8 = 255 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 




    // Rotate slider to vertical position 


    // Watch Bluetooth connection 
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.connectionChanged(_:)), name: NSNotification.Name(rawValue: BLEServiceChangedStatusNotification), object: nil) 

    // Start the Bluetooth discovery process 
    _ = btDiscoverySharedInstance 
    } 

    deinit { 
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: BLEServiceChangedStatusNotification), object: nil) 
    } 

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

    self.stopTimerTXDelay() 
    } 

    @IBAction func positionSliderChanged(_ sender: UISlider) { 
    self.sendPosition(UInt8(sender.value)) 




    } 

    func connectionChanged(_ notification: Notification) { 
    // Connection status changed. Indicate on GUI. 
    let userInfo = (notification as NSNotification).userInfo as! [String: Bool] 

    DispatchQueue.main.async(execute: { 
     // Set image based on connection status 
     if let isConnected: Bool = userInfo["isConnected"] { 
     if isConnected { 
      self.imgBluetoothStatus.image = UIImage(named: "Bluetooth_Connected") 

      // Send current slider position 
      self.sendPosition(UInt8(self.positionSlider.value)) 
     } else { 
      self.imgBluetoothStatus.image = UIImage(named: "Bluetooth_Disconnected") 
     } 
     } 
    }); 
    } 

    func sendPosition(_ position: UInt8) { 
    // Valid position range: 0 to 180 

    if !allowTX { 
     return 
    } 

    // Validate value 
    if position == lastPosition { 
     return 
    } 
    else if ((position < 0) || (position > 180)) { 
     return 
    } 

    // Send position to BLE Shield (if service exists and is connected) 
    if let bleService = btDiscoverySharedInstance.bleService { 
     bleService.writePosition(position: position) 
     lastPosition = position; 

     // Start delay timer 
     allowTX = false 
     if timerTXDelay == nil { 
     timerTXDelay = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.timerTXDelayElapsed), userInfo: nil, repeats: false) 
     } 
    } 
    } 

    func timerTXDelayElapsed() { 
    self.allowTX = true 
    self.stopTimerTXDelay() 

    // Send current slider position 
    self.sendPosition(UInt8(self.positionSlider.value)) 
    } 

    func stopTimerTXDelay() { 
    if self.timerTXDelay == nil { 
     return 
    } 

    timerTXDelay?.invalidate() 
    self.timerTXDelay = nil 
    } 





} 

Im BTService gibt es eine didUpdateValueFor Funktion und ich würde die it Variable wie zum Viewcontroller gesendet werden und es haben als BottomLabel festgelegt.

+0

@JoeBlow Die Datei ist "BTService.swift" – Matt

+0

Wie liest du diese "Servicedatei"? Ist das eine statische Datei, etwas periodisch aktualisiert oder sehr dynamisch? Es sollte ziemlich einfach sein, eine Datei in eine Zeichenkette zu lesen, aber ohne weitere Details ist es schwer, ihnen zu helfen. Welchen Code hast du ausprobiert? Das wäre auch hilfreich. Wie eine andere Person fragt - bitte poste mehr Code. Vielen Dank. – dfd

+0

@dfd Ich habe meine Frage mit Code und einer besseren Erklärung aktualisiert – Matt

Antwort

2

sollte es ähnlich sein, um Ihre bestehenden BLEServiceChangedStatusNotification:

definieren den Namen:

let BLEServicePeripheralChangedNotification = "kBLEServicePeripheralChangedNotification" 

fügen Sie den Beobachter in viewDidLoad:

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.peripheralChanged(_:)), name: NSNotification.Name(rawValue: BLEServicePeripheralChangedNotification), object: nil) 

entfernen Sie den Betrachter in deinit:

NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: BLEServicePeripheralChangedNotification), object: nil) 

fügen Sie die Funktion:

func peripheralChanged(_ notification: Notification) { 
    // peripheral status changed. Indicate on GUI. 
    let userInfo = (notification as NSNotification).userInfo as! [String: NSString] 
    if let it: NSString = userInfo["it"] { 
    //BottomLabel should be bottomLabel in declaration! 
    BottomLabel.text = it 
    } 
} 

die Post Notification Center hinzufügen:

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){ 

    let it = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue) 

    if(it != nil){ 
     print("Val: \(it)") 
     let itDetails = ["it": it] 
     NotificationCenter.default.post(name: Notification.Name(rawValue: BLEServicePeripheralChangedNotification), object: self, userInfo: itDetails) 
    } 

} 

PS: BottomLabelbottomLabel in Erklärung sein sollte.

Verwandte Themen