1

I am working through a Swift 2 Cocoa Async Socket tutorial which was downloaded from https://github.com/nickyhuyskens/SwiftCocoaAsyncSocketTutorial It was written in Swift 2 and I am working with Xcode 8 / Swift 3. The conversion seem fairly good with only a few correction except for one place where I cannot seem to make the needed correction.

Original Swift 2 code:

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)
    }
}

My Swift 3 changes:

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)
    }
}

When it gets to the line

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

the result is a "fatal error: unexpectedly found nil while unwrapping an Optional value". I have been looking at posts involving the changes in Swift 3 around change to getting the "sizeof" data and am not sure if the change to "MemoryLayout" was correct. Also I have tried a number of changes following posts involving Swift 3 changes to the use of the NSKeyedUnarchiver.unarchiveObjectWithData functionality but those also do not provide a working solution.

Any assistance or pointing to where the conversion solution can be found would be greatly appreciated.

FlapJack
  • 11
  • 4
  • Please, please, please stop using `!` to force unwrap objects. This error is being caused because you're force unwrapping objects and not properly handling the fact those objects could be `nil`. Your objects should either be optional or nonnull. You will continue to run into crashes like this if you continue to use `!`. It's not safe code. – AdamPro13 Jun 23 '17 at 21:53

1 Answers1

0
print(MemoryLayout<Data>.size == 8)

prints

true

Are You sure that this is what do You expect? It is the size of Data type, not the number of stored bytes.

the size of data (for example)

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

prints

10
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • Thanks for the response - I am definitely looking for the number of stored bytes in the second part of the socket data packet. This data packet must then be 'unpackaged' in the tag == 2 segment where it is using the "NSKeyedUnarchiver.unarchiveObject(with: data)" process to restore the original object. There seems to have been a significant change in how this is handled in Swift 3 and even after doing a fair bit of research and reading, I am not totally clear on how to have Swift 3 handle this properly. Thanks in advance in help with this. – FlapJack Jun 26 '17 at 05:19