Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with Swift 2.2 generics (Xcode 7.3)

I've got a frustrating situation with Swift 2.2 (Xcode 7.3). To simulate it, just create a variable in a user defined, generic class, and reference that class from someplace else. For example:

class A<T> {
    let genVar = 1
}

class MyViewController: UIViewController {
    let myVar = A<Int>() // crash is here
}

If you will run this code on a device running iOS 7 (iPhone 4, in my case), it will crash on the attempt of creating a variable of generic type. Here are the first lines of the device crash log:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: KERN_PROTECTION_FAILURE at 0x00298910
Triggered by Thread:  0

Thread 0 Crashed:
0   libswiftCore.dylib              0x006b1d64 0x4bd000 + 2051428
1   Phone                           0x001c76ec 0xab000 + 1165036
2   libswiftCore.dylib              0x006b307c 0x4bd000 + 2056316
3   libswiftCore.dylib              0x006b2f70 0x4bd000 + 2056048
4   libswiftCore.dylib              0x006b0f24 0x4bd000 + 2047780
5   libswiftCore.dylib              0x006b107c 0x4bd000 + 2048124
6   Phone                           0x0014e730 0xab000 + 669488
7   Phone                           0x00129390 0xab000 + 517008
8   UIKit                           0x31e9d9c4 -[UIClassSwapper initWithCoder:] + 188

On iOS 8 and 9 simulators/devices, the code above works okay.

Is Swift support for iOS 7 going to be dropped in the near future?

like image 350
Vas Avatar asked Mar 26 '16 12:03

Vas


1 Answers

I've been tripped up by what appears to be two bugs with Swift generics in iOS 7. Here's how to fix them.

Bug #1 - you must define a generic as the first property in your class before any others.

Example - this code fails:

public class TestIOS7<T> {

    private var x: Int?
}

let x = TestIOS7<String>()

But here's the workaround:

public class TestIOS7<T> {

    private var kludge: T?
    private var x: Int?
}

let x = TestIOS7<String>()

Bug #2: Class constraints seem completely broken.

Example - this code fails:

class ClassA<B: ClassB> { }

class ClassB { }

let x = ClassA <String>()

I have not found any workaround aside from removing the "ClassB" constraint and rewriting all the code to deal with the fact that basically, this language feature no longer exists. This is particular painful when you need to call an initializer of ClassB from ClassA - I had to rewrite that block with hardwired if/then/else for all my ClassB subclasses until Apple fixes this.

If someone does find a workaround to Bug #2 please let me know!

like image 61
alpsystems.com Avatar answered Sep 27 '22 17:09

alpsystems.com