Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling method using optional chaining on weak variable causes EXC_BAD_ACCESS

Update: This is fixed in Xcode 6 beta 6.

The following code causes an EXC_BAD_ACCESS on the delegate?.thing() line:

@class_protocol protocol Fooable {
  func foo()
}

class Bar : Fooable {
  func foo() {
  }
}

weak var delegate: Fooable?

let bar = Bar()
delegate = bar
delegate?.foo()

But everything seems right to me. In order for a variable to be weak, it must have optional type. So the variable delegate is optional. A weak variable's type must also be a class type, so I made the protocol a class protocol. Since I use optional chaining, I expect it to either 1) be nil, and do nothing, or 2) not be nil, and call the method, which should succeed. However, it crashes.

Could it be that optional chaining is not atomic and doesn't retain the expression and the object somehow gets deallocated in between the check for nil and the subsequent call?

Interestingly, if you eliminate the variable bar and assign it directly as delegate = Bar(), the crash goes away. This is really perplexing because assigning an expression to a variable and then assigning the variable and assigning the expression directly should generally behave the same.

like image 951
user102008 Avatar asked Jun 11 '14 23:06

user102008


1 Answers

I suspect the reason weak var delegate: Fooable?is not working is because that line of code, which is using optional chaining, is checking for protocol conformance.

According to Apple Swift Programming manual:

“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.”

If you substitute @class_protocol with @objc it should not crash. Also as per the manual, using @objc only allows the protocol to be adopted by classes (no structs or enums conformance).

like image 177
Raz Avatar answered Oct 19 '22 20:10

Raz