【问题标题】:Cocoa Async Socket Tutorial Code Conversion from Swift 2 to Swift 3Cocoa Async Socket 教程代码从 Swift 2 到 Swift 3 的转换
【发布时间】:2017-11-27 13:29:06
【问题描述】:

我正在学习从 https://github.com/nickyhuyskens/SwiftCocoaAsyncSocketTutorial 下载的 Swift 2 Cocoa Async Socket 教程,它是用 Swift 2 编写的,我正在使用 Xcode 8 / Swift 3。转换看起来相当不错,除了一些更正之外一个我似乎无法做出必要修正的地方。

原始 Swift 2 代码:

func socket(_ sock: GCDAsyncSocket!, didRead data: Data!, withTag tag: Int)
 {
    if tag == 1 {
         var bodyLength: Int16 = 0
         data.getBytes(&bodyLength, length: sizeof(Int16))
         print("Header received with bodylength: \(bodyLength)")
         socket.readDataToLength(UInt(bodyLength), withTimeout: -1, tag: 2)
    } else if tag == 2 {             
         let packet = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! Packet
         PacketHandler.HandlePacket(packet)
         socket.readDataToLength(UInt(sizeof(Int16)), withTimeout: -1, tag: 1)
        socket.readData(toLength: UInt(MemoryLayout<Int16>.size), withTimeout: -1, tag: 1)
    }
}

我的 Swift 3 变化:

func socket(_ sock: GCDAsyncSocket!, didRead data: Data!, withTag tag: Int) {
   if tag == 1 {
                    var bodyLength: UInt16 = 0
        bodyLength = (UInt16(MemoryLayout<Data>.size))
        print("Header received with bodylength: \(bodyLength)")
        socket.readData(toLength: UInt(bodyLength), withTimeout: -1, tag: 2)
    } else if tag == 2 {
        let packet = NSKeyedUnarchiver.unarchiveObject(with: data) as! Packet
        PacketHandler.HandlePacket(packet)
        socket.readData(toLength: UInt(MemoryLayout<Int16>.size), withTimeout: -1, tag: 1)
    }
}

当它到达线路时

let packet = NSKeyedUnarchiver.unarchiveObject(with: data) as! Packet

结果是“致命错误:在展开可选值时意外发现 nil”。我一直在查看涉及 Swift 3 中关于获取“sizeof”数据的更改的帖子,并且不确定对“MemoryLayout”的更改是否正确。此外,在涉及 Swift 3 更改使用 NSKeyedUnarchiver.unarchiveObjectWithData 功能的帖子之后,我尝试了一些更改,但这些也没有提供有效的解决方案。

任何帮助或指出可以找到转换解决方案的地方将不胜感激。

【问题讨论】:

  • 请,请,请停止使用! 强制解包对象。导致此错误的原因是您强制展开对象并且没有正确处理这些对象可能是nil 的事实。您的对象应该是可选的或非空的。如果您继续使用!,您将继续遇到这样的崩溃。这不是安全代码。

标签: ios swift3 swift2 bonjour code-conversion


【解决方案1】:
print(MemoryLayout<Data>.size == 8)

打印

true

您确定这是您所期望的吗?它是数据类型的大小,而不是存储的字节数。

数据的大小(例如)

let data = Data(bytes: [1,2,3,4,5,6,7,8,9,0])
print(data.count)

打印

10

【讨论】:

  • 感谢您的回复 - 我肯定在寻找套接字数据包第二部分中存储的字节数。该数据包必须在 tag == 2 段中“解包”,在该段中它使用“NSKeyedUnarchiver.unarchiveObject(with:data)”进程恢复原始对象。 Swift 3 中的处理方式似乎发生了重大变化,即使经过大量研究和阅读,我也不完全清楚如何让 Swift 3 正确处理这个问题。在此先感谢您的帮助。
猜你喜欢
  • 2017-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多