Problem with Swift 2.2 Generators (Xcode 7.3)

I have a disappointing situation with Swift 2.2 (Xcode 7.3). To simulate it, simply create a variable in a user-defined generic class and specify the class from another location. For example:

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

If you run this code on a device running iOS 7 (iPhone 4, in my case), it will crash when you try to create a variable of type generic. 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 fine.

Is support for Swift supported for iOS 7 in the near future?

+7
ios swift
source share
4 answers

I went astray, apparently due to two bugs with Swift generics in iOS 7. Here's how to fix them.

Mistake # 1 - you must define a shared object as the first property in your class before any others.

Example - this code does not work:

 public class TestIOS7<T> { private var x: Int? } let x = TestIOS7<String>() 

But here is a workaround:

 public class TestIOS7<T> { private var kludge: T? private var x: Int? } let x = TestIOS7<String>() 

Mistake # 2: Class restrictions seem to be completely broken.

Example - this code does not work:

 class ClassA<B: ClassB> { } class ClassB { } let x = ClassA <String>() 

I did not find a workaround other than removing the "ClassB" restriction and rewriting all the code to deal with the fact that basically this language feature no longer exists. This is especially painful when you need to call the ClassB initializer from ClassA - I had to rewrite this block with hardwired if / then / else for all my ClassB subclasses until Apple fixes it.

If someone finds a workaround for Bug # 2, please let me know!

+3
source share

As this error suggests that you have the following possible workarounds:

  • make the class not shared
  • remove value property
  • swap object and value property declarations
  • initialize an object in init

Probably the best solution is to initialize the object in init :

 class A<T> { let genVar: Int init() { genVar = 1 } } class MyViewController: UIViewController { let myVar = A<Int>() // no crash } 
+1
source share

We faced the same problem.

A workaround has been detected, although this would at least enable us to support iOS7 without significant rewriting.
It seems that all subclasses should also be shared so that the parent generic file works correctly in iOS7.
The type of the generic subclass does not matter, and it should not be the parent type.

I also posted this answer to the bug discussion of simpleBob.

Example:

 // This heavily pollutes the codebase, so let keep track of it but using a common meaningless generic value so we can find and destroy later when we no longer support iOS7 protocol iOS7SwiftGenericFixProtocol {} struct iOS7SwiftGenericFixType: iOS7SwiftGenericFixProtocol {} class GenericClass<T> { var value: T? let attribute = 0 } class GenericSubclass<Element: iOS7SwiftGenericFixProtocol>: GenericClass<Int> { let otherAttribute = 0 } let _ = GenericSubclass<iOS7SwiftGenericFixType>() 
0
source share

With Xcode 7.3.1, the only problem with my common class was that it inherited from NSObject. Removing inheritance was enough; the order in which the properties were declared did not matter.

0
source share

All Articles