Khairil Ushan
Khairil Ushan

Reputation: 2458

Swift Generic Class

I have a class like this

// a.swift
public class ComServiceString<Result>: ComService<Result> {    
    override func execute() {
        if (method == Method.GET) {
            manager.GET(getUrl(),
                parameters: nil,
                success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
                    self.onSuccessListener?(self.parseResult(responseObject.description))
                },
                failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
                    println("Error: " + error.localizedDescription)
                    var errorSd = ComServiceError(error.localizedDescription)
                    if (operation.response != nil) {
                        errorSd.errorCode = operation.response.statusCode
                    }
                    self.onFailedListener?(errorSd)
                }
            )
        }
    }

    func parseResult(result: String) -> Result? {
        fatalError("This method need to be implemented")
    }
}

and I extend it to a new class like this

// b.swift:
public class BranchListService<T>: ComServiceString<BranchListModel> {

    override func parseResult(result: String) -> BranchListModel? {
        let branchListMode = BranchListModel(stringResult: result)
        return branchListMode
    }
}

my BranchListModel looks like this

public class BranchListModel {
    public var total = 0
    public var stringResult = ""

    init() {}

    init (stringResult result: String) {
        self.stringResult = result
        if let jsonArray = JSONUtil.stringToJSONArray(result) {
            if let resultObject = jsonArray[0] as? NSDictionary {
                if let total = resultObject["total"] as? NSString {
                    self.total = total.integerValue;
                }
            }
        }
    }
}

but I got BAD_ACCESS error in this line:

let branchListMode = BranchListModel(stringResult: self.resultString)

inside parseResult function on b.swift. I'm still learning this language with trying to convert my java code to swift. Do you guys know what's wrong from the code?

Upvotes: 1

Views: 296

Answers (1)

findall
findall

Reputation: 2193

I think there is a bug of the Swift compiler. I've tested a relatively-simplified code below and that crashed in the same way.

class ResultParser<T> {
    func parse(result: String) -> T? { abort() }
}

class MyResultParser<T>: ResultParser<Int> {
    override func parse(result: String) -> Int? {
        return result.toInt()
    }
}

let parser: ResultParser<Int> = MyResultParser<()>()
parser.parse("2525")

At the moment, the Swift compiler cannot correctly treat virtual functions directly receiving and/or returning values, whose type is generic. I guess the compiler regards T as a pointer (object) value whatever an actual substituted type is.

I've found a workaround to do nearly the same thing.

class Box<T> {
    let raw: T
    init(_ raw: T) { self.raw = raw }
}

class ResultParser<T> {
    func parse(result: String) -> Box<T?> { abort() }
}

class MyResultParser<T>: ResultParser<Int> {
    override func parse(result: String) -> Box<Int?> {
        return Box(result.toInt())
    }
}

In the code above, the returned value is wrapped in the Box<>. Box<> is an object, so that works no matter whether or not the compiler can tell value types from object types.

Upvotes: 1

Related Questions