I have this code in my Xcode playground that gives me EXC_BAD_ACCESS
error on last line:
protocol SomeProtocol: class {
func test()
}
class SomeClass: SomeProtocol {
func test(){}
}
struct Weak<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
var value: SomeProtocol = SomeClass()
var w = Weak(value)
w.value?.test() // EXC_BAD_ACCESS
If I add @objc
to protocol definition than code executes without any errors:
import Foundation
@objc protocol SomeProtocol: class {
func test()
}
class SomeClass: SomeProtocol {
@objc func test(){}
}
struct Weak<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
var value: SomeProtocol = SomeClass()
var w = Weak(value)
w.value?.test()
I suspect that these lines of Apple documentation somehow relate to my case:
Even if you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you want to be able to check for protocol conformance.
But I do not understand why it does not work without @objc
. Could someone explain?
Swift currently does not handle using non-class types with generics well.
The actual location of the EXC_BAD_ACCESS
is when the result of Weak(value)
is assigned to var w
. You can see this by adding the println
statements around the var w = Weak(value)
.
To get around these problems with Swift you'll need to Box values with non-class types to use them with generics.
Hopefully in the next few versions of Swift Apple will fix these issues and we'll no longer need to box values.
final class Box<T> {
private var value: T
init(_ value: T) {
self.value = value
}
var unbox: T {
return value
}
}
protocol SomeProtocol : AnyObject {
func test()
}
class SomeClass: SomeProtocol {
func test(){
println("Test")
}
}
struct Weak<T: AnyObject> {
weak var value: T?
init(_ value: T) {
println("Weak Init Start")
self.value = value
println("Weak Init Stop")
}
}
var value: SomeProtocol = SomeClass()
//Method in Question
println("Before Weak Init")
// var w = Weak(value) // EXC_BAD_ACCESS
println("After Weak Init")
//w.value?.test()
// Method with Box
var box = Box(value)
var w = Weak(box)
w.value?.unbox.test() // prints "Test"
w = Weak(Box(value))
w.value?.unbox.test() // nil, since nothing retains the Box(value) result
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.