首页 > 解决方案 > 不工作的代表

问题描述

我刚开始使用委托和协议,我认为它非常有用。在我的项目中,当我尝试委托给 ViewController 时,它工作得很好,因为它不适用于我创建的其他类。我不明白为什么。我尝试将数据从类 ServerArtNet 传输到类 FixtureControl。但它不起作用。你知道为什么吗?

服务器艺术网

protocol ArtNetDelegate: class {
func receivedFixtureControll(intS: Float, StrobeS:Float, Red: Float, Green: Float, Blue: Float)
}

class ServerArtNet: NSObject {
  weak var delegate:ArtNetDelegate?

let serverUDP = ServerUDP()

func artNetReceive (data:Data) {
    let DMX_Universe_Bytes: [UInt8] = [DMX_Universe, 0]

    var received = [UInt8]()
    received.append(contentsOf: data)
    if (received.count > 17) {
        let number_of_received_chanel = (UInt16(received[17]<<8) + UInt16(received[16]))
        if (received[0...6] == ArtNetHead[0...6]) && (received[7...11] == OpOutput[0...4]) && (received[14...15] == DMX_Universe_Bytes[0...1]) && number_of_received_chanel>0 {
            let intensityScreen:Float = received[18].fromDMX()
            let shutter:Float = received[19].fromDMX()
            let red:Float = received[20].fromDMX()
            let green:Float = received[21].fromDMX()
            let blue:Float = received[22].fromDMX()

            delegate?.receivedFixtureControll(intS:intensityScreen,StrobeS:shutter, Red: red, Green: green, Blue: blue)
            }
    }
}
}

夹具控制

import UIKit

class FixtureControll: NSObject {

let serverArtNet = ServerArtNet()

override init() {
    super.init()
    serverArtNet.delegate! = self
}

func Fixture(intS: Float, strobS:Float, red:Float, green:Float, blue:Float) {
//        Working with data 
    }

}

extension FixtureControll: ArtNetDelegate {
    func receivedFixtureControll(intS: Float, StrobeS:Float, Red: Float, Green: Float, Blue: Float) {
        Fixture(intS: intS, strobS: StrobeS, red: Red, green: Green, blue: Blue)
    }
}

服务器UDP

import UIKit
import CocoaAsyncSocket

 protocol ServerUDPDelegate: class {
func receiveData(data: Data, address: String)
 }


class ServerUDP: NSObject, GCDAsyncUdpSocketDelegate {
    weak var delegate: ServerUDPDelegate?

    let IP = "255.255.255.255"
    let destinationIP = "255.255.255.255"
    let PORT:UInt16 = 6454
    var socket:GCDAsyncUdpSocket!

    override init() {
        super.init()
        setupConnection()
    }

    func setupConnection(){
        socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)

        do {
            try socket.bind(toPort: PORT)
        }
        catch {
            print("Binding error: ", error.localizedDescription)
        }
        do {
            try socket.beginReceiving()
        }
        catch {
            print("Connecting error: ", error.localizedDescription)
        }
        do {
            try socket.enableBroadcast(true)
        }
        catch {
            print("brodcust error: ", error.localizedDescription)
        }

    }

func StopServer() {
    socket.close()
}


//    Receiving data from port
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext withFilterContex: Any?) {
//        print("DID RECEIVE DATA")

//    Convert NSData to string to get Address info
    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
    do {
        try address.withUnsafeBytes { (pointer:UnsafePointer<sockaddr>) -> Void in
            guard getnameinfo(pointer, socklen_t(address.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
                throw NSError(domain: "domain", code: 0, userInfo: ["error":"unable to get ip address"])
            }
        }
    } catch {
        print(error)
        return
    }
    let senderAddress = String(cString:hostname)
    delegate?.receiveData(data: data, address: senderAddress)
}
}

扩展

extension ViewController: ServerUDPDelegate {
func receiveData(data: Data, address: String) {
    serverArtNet.artNetReceive(data: data)
    }
}

视图控制器

import UIKit
import AVFoundation
import AudioToolbox

class ViewController: UIViewController{

let serverUDP = ServerUDP()


var ToolbarAppeare = false

@IBAction func InfoButton(_ sender: UIBarButtonItem) {
    self.performSegue(withIdentifier: "Information", sender:sender)
}
@IBAction func TouchTap(_ sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        ToolbarAppeare = !ToolbarAppeare
        self.navigationController?.setNavigationBarHidden(ToolbarAppeare, animated: true)

    }
}
override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}
override var prefersStatusBarHidden: Bool {
    return true
}


override func viewDidLoad() {
    super.viewDidLoad()
    serverUDP.delegate = self
}

func applicationWillTerminate(application: UIApplication) {
    serverUDP.StopServer()
}


func UIColorSet (Red:Float, Green:Float, Blue:Float, Alpha:Float) {
    self.view.backgroundColor = UIColor(red: CGFloat(Red), green: CGFloat(Green), blue: CGFloat(Blue), alpha: CGFloat(Alpha))
}

}

标签: swiftdelegatesprotocols

解决方案


正如我在评论中所写,您实例化了太多实例。这是清除此类不需要的实例创建的示例。


服务器艺术网

protocol ArtNetDelegate: class {
    func receivedFixtureControll(intS: Float, strobeS: Float, red: Float, green: Float, blue: Float)
}

class ServerArtNet: NSObject, ServerUDPDelegate {
    weak var delegate: ArtNetDelegate?
    
    let serverUDP: ServerUDP
    
    override init() {
        serverUDP = ServerUDP() //### Instatiate a new `ServerUDP` dedicated for this instance
        super.init()
        serverUDP.delegate = self
    }
    
    //### This class should manage all lower level events
    func receiveData(data:Data, address: String) {
        let DMX_Universe_Bytes: [UInt8] = [DMX_Universe, 0]
        
        var received = [UInt8]()
        received.append(contentsOf: data)
        if (received.count > 17) {
            let number_of_received_chanel = (UInt16(received[17]<<8) + UInt16(received[16]))
            if (received[0...6] == ArtNetHead[0...6]) && (received[7...11] == OpOutput[0...4]) && (received[14...15] == DMX_Universe_Bytes[0...1]) && number_of_received_chanel>0 {
                let intensityScreen:Float = received[18].fromDMX()
                let shutter:Float = received[19].fromDMX()
                let red:Float = received[20].fromDMX()
                let green:Float = received[21].fromDMX()
                let blue:Float = received[22].fromDMX()
                
                delegate?.receivedFixtureControll(intS:intensityScreen,  strobeS: shutter, red: red, green: green, blue: blue)
            }
        }
    }
    
    func stopServer() {
        serverUDP.stopServer()
    }
}

这个类应该负责像ServerUDP. 所以,我让这个类符合ServerUDPDelegate.


夹具控制

class FixtureControll {
    
    //### Do NOT instantiate a new `ServerArtNet` here.
    
    func fixture(intS: Float, strobeS: Float, red: Float, green: Float, blue: Float) {
        //        Working with data
    }
}

在我看来,这个类的每个实例都不需要有自己的ServerArtNet. 删除它。


服务器UDP

protocol ServerUDPDelegate: class {
    func receiveData(data: Data, address: String)
}

class ServerUDP: NSObject, GCDAsyncUdpSocketDelegate {
    weak var delegate: ServerUDPDelegate?
    
    let IP = "255.255.255.255"
    let destinationIP = "255.255.255.255"
    let port: UInt16 = 6454
    var socket: GCDAsyncUdpSocket!
    
    override init() {
        super.init()
        setupConnection()
    }
    
    func setupConnection(){
        socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)
        
        do {
            try socket.bind(toPort: port)
        }
        catch {
            print("Binding error: ", error.localizedDescription)
        }
        do {
            try socket.beginReceiving()
        }
        catch {
            print("Connecting error: ", error.localizedDescription)
        }
        do {
            try socket.enableBroadcast(true)
        }
        catch {
            print("brodcust error: ", error.localizedDescription)
        }
    }
    
    func stopServer() {
        socket.close()
    }
    
    //    Receiving data from port
    func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext withFilterContex: Any?) {
        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
        do {
            try address.withUnsafeBytes { (sockadrPtr: UnsafePointer<sockaddr>) -> Void in
                guard getnameinfo(sockadrPtr, socklen_t(address.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
                    throw NSError(domain: "domain", code: 0, userInfo: ["error":"unable to get ip address"])
                }
            }
        } catch {
            print(error)
            return
        }
        let senderAddress = String(cString: hostname)
        delegate?.receiveData(data: data, address: senderAddress)
    }
}

只是重命名了一些标识符以遵循 Swift 约定。


ViewController 及其扩展

class ViewController: UIViewController {
    
    var serverArtNet: ServerArtNet!
    
    var toolbarAppeare = false
    
    @IBAction func InfoButton(_ sender: UIBarButtonItem) {
        self.performSegue(withIdentifier: "Information", sender:sender)
    }
    @IBAction func TouchTap(_ sender: UITapGestureRecognizer) {
        if sender.state == .ended {
            toolbarAppeare = !toolbarAppeare // You can use `toolbarAppeare.toggle()` in Swift 4.2
            self.navigationController?.setNavigationBarHidden(toolbarAppeare, animated: true)
            
        }
    }
    override var preferredStatusBarStyle : UIStatusBarStyle {
        return .lightContent
    }
    override var prefersStatusBarHidden: Bool {
        return true
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        serverArtNet = ServerArtNet()
        serverArtNet.delegate = self
    }
    
    func applicationWillTerminate(application: UIApplication) {
        //### Do NOT access lower level classes (`ServerUDP`) directly.
        serverArtNet.stopServer()
    }
    
    func uiColorSet(red:Float, green:Float, blue:Float, alpha:Float) {
        self.view.backgroundColor = UIColor(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: CGFloat(alpha))
    }
}

extension ViewController: ArtNetDelegate {
    func receivedFixtureControll(intS: Float, strobeS: Float, red: Float, green: Float, blue: Float) {
        let fixtureControl = FixtureControll()
        fixtureControl.fixture(intS: intS, strobeS: strobeS, red: red, green: green, blue: blue)
    }
}

这个类应该负责delegateServerArtNet


一般来说,你不应该声明类似的属性let propName = ClassName(),除非你有明确的意图来创建一个新的实例


推荐阅读