Simple Swift Class Does Not Compile

Simple Swift class does not compile

As I point out in comments, your example seems to compile fine on beta 2, although it still won't work for a couple of reasons, for encoderWithCoder to be of any use, ClassWithOneArray needs to:

  1. declare conformance with NSCoding,
  2. implement NSCoding,
  3. inherit from NSObject or implement NSObjectProtocol, and,
  4. use a non-mangled name.

All told, that means:

@objc(ClassWithOneArray)
class ClassWithOneArray:NSObject, NSCoding {
var myArray: String[]
init(myArray: String[]) {
self.myArray = myArray
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(myArray, forKey: "myArray")
}
init(coder aDecoder: NSCoder) {
self.myArray = aDecoder.decodeObjectForKey("myArray") as String[]
}
}

Also it seems as if the simple methods of testing archiving aren't available in the playground, probably because the classes don't get properly registered.

let foo = ClassWithOneArray(myArray:["A"])

let data = NSKeyedArchiver.archivedDataWithRootObject(foo)

let unarchiver = NSKeyedUnarchiver(forReadingWithData:data)
unarchiver.setClass(ClassWithOneArray.self, forClassName: "ClassWithOneArray")
let bar = unarchiver.decodeObjectForKey("root") as ClassWithOneArray

Why generics don't compile?

I'm not a Swift developer, but having seen similar problems in Java, I suspect the problem is that at the moment you're declaring a type parameter called String because you're declaring class FooTranslator<String> - so the type argument in Translator<String> is just that type parameter, which has no constraints. You don't want a type parameter at all, I suspect (i.e. you don't want your FooTranslator to be a generic class itself.)

As noted in comments, in Swift subclasses of a generic class also have to be generic. You could possibly declare a throw-away type parameter, like this:

class FooTranslator<T>:Translator<String>

which still avoids declaring a new type parameter called String, which was what was causing the problem. It means you're introducing a new type parameter when you don't want any type parameters, but it's possibly better than nothing...

This is all on the assumption that you really need a subclass, e.g. to add or override members. On the other hand, if you just want a type which is exactly the same as Translator<String>, you should use a type alias instead:

typealias FooTranslator = Translator<String>

Or even mix the two in a horrible way, if you genuinely want a subclass but don't want to have to refer to it in a generic way:

class GenericFooTranslator<T>:Translator<String>
typealias FooTranslator = GenericFooTranslator<Int>

(Note that the Int here is deliberately not String, to show that the T in Translator isn't the same as the T in FooTranslator.)

Why does XCode suggest (and compile) non-existant object properties?

On every iOS and MacOS X version, there are three important version numbers: The version number of the SDK that you are using (what you use in your compiler), the version number of the lowest iOS or MacOS X version that allows your app to run, and the version number of the actual device your code is running on.

The SDK number tells the compiler which OS methods you can call. If your SDK is MacOS X 10.9 then you cannot call methods from MacOS X 10.10, the compiler doesn't allow it.

If your deployment version (the lowest version that allows the app to run) is for example 10.9 and the SDK is 10.10 then methods that only exist will crash if you try to call them when running on 10.9. You need to check this manually; Swift 2 has methods that make this very easy.

In this situation, the app will not run on 10.8 at all. It will run on 10.9 but crash if you use 10.10 methods. It will run fine on 10.9.

The idea behind the setup is that it lets you use new features running on a new OS version, while being able to run on an old OS version, assuming you are careful to avoid new calls.

If that's too complicated for you, either use the 10.9 SDK (no 10.10 calls for you, ever), or deploy on 10.10 only (your app won't run on 10.9).

Swift generic function does not compile in testing

This is reasonable for the compiler. Swift allows type conversion for a Concrete type to a Protocol based variable assignment.

However, Swift doesnot allow converting a set of Concrete Types to a set/array of Protocol by converting each. This is reasonable because of the following reasons:

Let suppose we have this constructs in place:

protocol IntType {}
extension Int: IntType{}

Now lets do the obvious thing:

let item = 12
let item2:IntType = item

Then the one that will look obvious to the eye: This wont compile for good reason.

let a = [1,2,3]
let b: [IntType] = a

Lets inspect the size of each Type before moving ahead:

sizeofValue(item)   //8
sizeofValue(item2) //40

An array is a contagious memory of 8 bytes. So is Array a contagious memory of 40 bytes.

When we did this:

let b: [IntType] = a

We essentially tell the compiler to convert 8 bytes of array into 40 bytes of array and store it. Now as the array is contagious it has to destruct or reshuffle which is expensive task to do so. This hinders the performance and obviously you lose the type safety.

The compiler could this this transformation but Swift team decided for good reason that the user need to be explicit if they want this type transformation for 2 reasons: Performance and Type Safety.

Any thoughts on why this Swift code does not compile?

The syntactic sugar for Array and Dictionary changed in beta 3. This code won't work in the first or second beta, but will work in a newer version.

If you want the code to work in an earlier version, just remove the syntactic sugar:

protocol Serializable
{
init(dictionary: Dictionary<NSObject, AnyObject>)
}


Related Topics



Leave a reply



Submit