Weird Issue During Migration from Swift 2 to Swift 3: Initializer Has Different Argument Names from Those Required by Protocol

Weird issue during migration from Swift 2 to Swift 3: Initializer has different argument names from those required by protocol

In Swift 2 we used to have NSData with the initializer init(bytes:length:). Since Apple has done a lot of renaming in Swift 3, NSData is called Data and the initializer is called init(bytes:count:) now.

So everything you need to do is to update your KeyType protocol:

public protocol KeyType {
init(bytes: UnsafeRawPointer, count: Int) // change "length" to "count"
func withSlice(_ f: (Slice) -> ())
func asData() -> Data
}

How to create a generic function in Swift that will reject the given parameter unless it is an Optional?

You might want to give this protocol a better name, but I don't foresee any problems with it as-is, unless you're making your own ExpressibleByNilLiteral types that don't wrap.

protocol ExpressibleByNilLiteral: Swift.ExpressibleByNilLiteral {
associatedtype Wrapped
}

extension Optional: ExpressibleByNilLiteral { }

func onlyCallableByAnOptional<Optional: ExpressibleByNilLiteral>(_ optional: Optional) -> Optional.Wrapped? {
optional as? Optional.Wrapped
}

Recommendation: use an initializer. (Downside is the argument label being necessary to disambiguate, but I personally like the explicitness because of how weird this case is. i.e. Swift makes it easy to enforce that something is not optional, but not vice versa.)

extension Optional: ExpressibleByNilLiteral {
init<Optional: ExpressibleByNilLiteral>(optional: Optional) where Optional.Wrapped == Wrapped {
self = optional as? Wrapped
}
}

+

if let v = Optional(optional: i) {  // ERROR, as was desired.
print("integer \(v)")
}
if let v = Optional(optional: oi) { // OK, as expected.
print("optional integer \(v)")
}

Swift: Self.init called multiple times in initializer

I suspect this is a bad diagnostic (i.e the wrong error message). It would be very helpful if you had a full example we could experiment with, but this line doesn't make sense (and I suspect is the underlying problem):

    super.init(document: self, gravlNode: node)

You can't pass self to super.init. You're not initialized yet (you're not initialized until you've called super.init). For example, consider the following simplified code:

class S {
init(document: AnyObject) {}
}

class C: S {
public init() {
super.init(document: self)
}
}

This leads to error: 'self' used before super.init call which I believe is the correct error.

EDIT: I believe Hamish has definitely uncovered a compiler bug. You can exploit it this way in Xcode 8.3.1 (haven't tested on 8.3.2 yet):

class S {
var x: Int
init(document: S) {
self.x = document.x
}
}

class C: S {
public init() {
super.init(document: self)
}
}

let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list

NSDate code not migrating to Swift 3.0

You can easily remove the convenience from the init method.

extension Date {
init(posixTime: Double) {
self.init(timeIntervalSince1970: Double(posixTime) / 1000.0)
}
}

Seems like the migration tool has incorrectly convert the self instance to NSDate in your previous code.

Weird behaviour on Swift protocol methods

As we know from Swift documentation for functions, foo and bar are external names for aString parameter. So technically he have exactly the same function with just different names of parameters that is completely legal in Objective-C:

id<MyProtocol> myVar;
[myVar myProtocolWithBar:@""];
[myVar myProtocolWithFoo:@""];

I think it is a bug in Swift compiler! File a report: http://bugreport.apple.com



Related Topics



Leave a reply



Submit