Creating an instance of T within a swift generic causing EXC_BAD_ACCESS on accessing Ts members

I am trying to create a generic which will create and store objects of type T. However, when i do this it appears that the create function will only create an instance of the constraining type rather than the specified type.


  1. Is this by design,I believe this used to create the specified type in earlier versions of xcode. Current one in use is 6.3.2?
  2. How do i get it to create the specified type?



import Foundation
class Base {
    var id: Int

    init() {
        id = 0
        println("Initializing base")
    }
}
class Derived: Base {
    var name: String

    override init() {
        name =  "Undefined"
        super.init()
        println("Initializing derived")
    }
}
class Container<T: Base> {
    var collection: [T]

    init() {
        collection = []
        println("Initiazing container with type \(T.self)")
    }

    func create() -> T {
        var newT = T()
        println("Created New T() -> \(newT), but should have been \(T.self)")
        return newT
    }
}
var derivedContainer = Container<Derived>()
var derived = derivedContainer.create()
derived.id = 66 // OK
println("Created type was \(derived)")
//println("Derived name=\(derived.name)") // Thread 1: EXC_BAD_ACCESS(code=2, address=0x1001c5a38)
//derived.name = "wowzer" // Thread 1: EXC_BAD_ACCESS(code=2, address=0x1001d4710)


Output, missing Derived initialization:


Initiazing container with type template_test.Derived
Initializing base
Created New T() -> template_test.Base, but should have been template_test.Derived
Created type was template_test.Base
Answered by LCS in 19135022

To make this sort of thing work in Swift 1.2 (Xcode 6.3.2), you will probably need to give your Base class a required initializer and store a reference to the type in each container.


class Base {
    var id: Int
  
    required init() {
        id = 0
        println("Initializing base")
    }
}
class Derived: Base {
    var name: String
  
    required init() {
        name =  "Undefined"
        super.init()
        println("Initializing derived")
    }
}
class Container<T: Base> {
    var elementType: Base.Type
    var collection: [T]
  
    init() {
        collection = []
        elementType = T.self
        println("Initiazing container with type \(T.self)")
    }
  
    func create() -> T {
        let newT = elementType()
        println("Created New T() -> \(newT), but should have been \(T.self)")
        return newT as! T
    }
}
var derivedContainer = Container<Derived>()
var derived = derivedContainer.create()
derived.id = 66 // OK
println("Created type was \(derived)")
println("Derived name=\(derived.name)")
derived.name = "wowzer"


The good news is that Swift 2 will work properly with the code in your original post (with minor updates for Swift 2 like print() and T.init()), and create the subclass type declared when creating the container (tested in Xcode 7 beta 2).

Accepted Answer

To make this sort of thing work in Swift 1.2 (Xcode 6.3.2), you will probably need to give your Base class a required initializer and store a reference to the type in each container.


class Base {
    var id: Int
  
    required init() {
        id = 0
        println("Initializing base")
    }
}
class Derived: Base {
    var name: String
  
    required init() {
        name =  "Undefined"
        super.init()
        println("Initializing derived")
    }
}
class Container<T: Base> {
    var elementType: Base.Type
    var collection: [T]
  
    init() {
        collection = []
        elementType = T.self
        println("Initiazing container with type \(T.self)")
    }
  
    func create() -> T {
        let newT = elementType()
        println("Created New T() -> \(newT), but should have been \(T.self)")
        return newT as! T
    }
}
var derivedContainer = Container<Derived>()
var derived = derivedContainer.create()
derived.id = 66 // OK
println("Created type was \(derived)")
println("Derived name=\(derived.name)")
derived.name = "wowzer"


The good news is that Swift 2 will work properly with the code in your original post (with minor updates for Swift 2 like print() and T.init()), and create the subclass type declared when creating the container (tested in Xcode 7 beta 2).

Thanks LCS. Will use required for now.

Creating an instance of T within a swift generic causing EXC_BAD_ACCESS on accessing Ts members
 
 
Q