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.
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 #PartiallyFinite, I had to play with the code a little too. Apple's iBook on Swift has a blurb about this that may help (with a protocol named ExampleProtocol and a class SimpleClass that conforms to that protocol):
"Even though the variable protocolValue has a runtime type of SimpleClass, the compiler treats it as the given type of ExampleProtocol. This means that you can’t accidentally access methods or properties that the class implements in addition to its protocol conformance.”
That said, you should be able to call foo() on your delegate (barring it doesn't go away before calling it), but just remember the delegate here is declared to be of type Fooable?, not Bar, under the hood. This may be a bug, but I got it to work by entering:
weak var delegate: Bar? = bar
delegate?.foo()
Related
Caveat: I've been coding in Swift for about 2 days!
I am following along with some simple tutorials to build a status menu application. The following is a reduction of my AppDelegate.swift class:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
#IBOutlet weak var statusMenu: NSMenu!
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)
func applicationDidFinishLaunching(aNotification: NSNotification) {
let icon = NSImage(named: "StatusBarImage")
icon?.setTemplate(true)
}
}
My question is, why does Xcode insist that my icon constant be an optional (it was also OK with me forcing it to be unwrapped). The tutorial didn't show that the ? was needed, but Xcode shows me the following error if I leave it out:
Value of optional type 'NSImage' not unwrapped; did you mean to use '!' or '?'?
(I'm using Xcode 6.4, if that makes a difference.)
From Document:
Declaration:
init?(named name: String) -> NSImage
Which means by default it's initialiser is an optional.
Return Value
The NSImage object associated with the specified name or nil if no
such image was found.
Discussion
The NSImage class may cache a reference to the returned image object
for performance in some cases. However, the class holds onto cached
objects only while the object exists. If all strong references to the
image are subsequently removed, the object may be quietly removed from
the cache. Thus, if you plan to hold onto a returned image object, you
must maintain a strong reference to it like you would any Cocoa
object. You can clear an image object from the cache explicitly by
calling the object’s setName: method and specifying nil for the image
name.
That's why it is asking you did you mean to use '!' or '?'
So if you use ! that means you are unwrapping optional value and if you use ? compiler will consider it as optional.
Because image named StatusBarImage might as well not be in the assets and it would result in bad access exception.
Actually Xcode is not forcing anything : if you check the NSImage documentation you will see that the NSImage initializer is a failable initializer.
Like #FruitAddict said the whole point of those initializers is to fail gracefully (by returning an optional with a nil value) when the object could not be created. Check Apple Developer Blog
By adding ! or this ? You know explicitly that imageNamed can returned you a nil.
And Compiler just makes sure that you know about it.
Specifically, how does Swift memory management work with optionals using the delegate pattern?
Being accustomed to writing the delegate pattern in Objective-C, my instinct is to make the delegate weak. For example, in Objective-C:
#property (weak) id<FooDelegate> delegate;
However, doing this in Swift isn't so straight-forward.
If we have just a normal looking protocol:
protocol FooDelegate {
func doStuff()
}
We cannot declare variables of this type as weak:
weak var delegate: FooDelegate?
Produces the error:
'weak' cannot be applied to non-class type 'FooDelegate'
So we either don't use the keyword weak, which allows us to use structs and enums as delegates, or we change our protocol to the following:
protocol FooDelegate: class {
func doStuff()
}
Which allows us to use weak, but does not allow us to use structs or enums.
If I don't make my protocol a class protocol, and therefore do not use weak for my variable, I'm creating a retain cycle, correct?
Is there any imaginable reason why any protocol intended to be used as a delegate protocol shouldn't be a class protocol so that variables of this type can be weak?
I primarily ask, because in the delegation section of the Apple official documentation on Swift protocols, they provide an example of a non-class protocol and a non-weak variable used as the delegate to their class:
protocol DiceGameDelegate {
func gameDidStart(game: DiceGame)
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(game: DiceGame)
}
class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
init() {
board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDidEnd(self)
}
}
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Should we take this as a hint that Apple thinks we should be using structs as delegates? Or is this simply a bad example, and realistically, delegate protocols should be declared as class-only protocols so that the delegated object can hold a weak reference to its delegate?
Here's the thing. In real life Cocoa programming, the delegate is likely to be an existing class. It is a class because it exists for some other purpose that only a class can satisfy - because Cocoa demands it.
For example, very often, to take iOS as an example, one view controller needs to act as another view controller's delegate for purposes of arranging a message back and forth between them. Ownership of the view controllers is dictated by the view controller hierarchy and by nothing else. So, in Swift, just as in Objective-C, you had better make that delegate property weak, because it would be terrible if one view controller suddenly took memory management ownership of another view controller!
So, in the real world of the Cocoa framework, there is serious danger of incorrect ownership or of a retain cycle. And that is the problem that weak solves. But it only works, as you rightly say, with classes.
The example in the book, however, is about some objects living off in an abstract made-up artificial Swift-only world. In that world, as long as you aren't in danger of circularity (retain cycle), there's no reason not to use structs and there's no reason to worry about memory management. But that world is not the world you will usually be programming in! And that world is not the framework Cocoa world that your Objective-C delegate pattern comes from and belongs to.
Yes, this example is a bit of an oddity.
Because the example uses a non-class protocol type, it has to expect a possible struct implementing the protocol, which means that the DiceGame instance owns its delegate. And indeed, that violates typical assumptions about the delegate pattern.
It doesn't lead to a reference cycle in this case because the DiceGameTracker is a fictional object that doesn't own the DiceGame itself — but in a real-world app it's possible, even likely, that a delegate might also be the owner of the delegating object. (For example, a view controller might own the DiceGame, and implement DiceGameDelegate so it can update its UI in response to game events.)
That kind of reference cycle would probably turn into a confusing mess if either the game, its delegate, or the type implementing one or both of those protocols were a value type — because value types are copied, some of the variables in your setup would end up being distinct copies of the game (or game's owner).
Realistically one would expect to use reference types (classes) to implement this anyway, even if the protocol declaration leaves open the possibility of doing it otherwise. Even in a hypothetical Swift-only world, it probably makes sense to do it that way... generally whenever you have something with long life, internal mutable state, and a usage pattern that has it being accessed by potentially multiple other actors, you want a class type, even if you can sort of fake otherwise with value types and var.
If you must have structs and emums in your protocol, then if you make your delegate nil just before you close the view controller, then this breaks the retain cycle. I verified this in Allocations in Instruments.
// view controller about to close
objectCreatedByMe.delegate = nil
It's an optional, so this is valid.
I have a swift project with a storyboard using Size Classes, a ViewController which conforms to the UITraitEnvironment protocol and have implemented the function traitCollectionDidChange.
When I first launch the app traitCollectionDidChange is called which seems reasonable - it allows developers to handle the first size class presented by the application, however the previousTraitCollection variable passed to it is nil. I can't check that this value is nil as its NOT optional, and accessing it in any way causes a crash. Changing the parameter to optional in the function declaration causes a build error, complaining that I have not implemented required methods in the protocol.
For now I have managed to work around this by creating a separate function which takes an optional variable of the same type that I can then check against, but I would like to know why this is happening.
If its any use to anyone at all, here is the function I am overriding
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection) {
// Accessing previousTraitCollection causes a crash
}
Can anyone shed any light on this?
You have to declare that the type of the argument is optional, because accessing it forces the compiler to try and unpack the address which causes the crash. Replace it with:
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
// Accessing previousTraitCollection causes a crash
}
I find the following code in UITableView class,
unowned(unsafe) var delegate: UITableViewDelegate?
so I wander how to define a unowned(unsafe) reference delegate for UIView, then I encounter the following error when I write the unowned(unsafe) keyword in my class,
/Users/larryhou/Documents/Xcode/AtomicElements/AtomicElements/AtomicElementView.swift:32:25: 'unowned' cannot be applied to non-class type 'AtomicElementViewDelegate?'
protocol AtomicElementViewDelegate:NSObjectProtocol
{
func didTap(target:AtomicElementView, sender:UITapGestureRecognizer)
}
I can only use weak keyword, but I want keep the reference until UIView is deallocated.
Those two designations - unowned and weak - are equivalent from the perspective of references. Where they differ is the presumption of existence - in Swift, unowned instances are presumed to always exist as long as reference to them does, whereas weak instances are optionals - they may exist, or they may not, so you need to use optional chaining or some other means of working with them.
In UIKit, the delegate pattern with UIView subclasses is to declare them as weak because the delegate is nearly always the view controller that owns the view that the subclass is a subview of. Declaring a delegate as strongly referenced in that situation would set up a reference cycle, hence delegates are typically declared with the weak keyword. If you have a different situation, you can allow your delegate to be strongly referenced by simply leaving out the weak keyword.
In this particular case, unowned (unsafe) is an artifact of being bridged from ObjC.
how to define a unowned(unsafe) reference delegate for UIView
You can't. And you shouldn't want to. unowned(unsafe) is a way of expressing the Objective-C non-ARC assign policy, i.e. no memory management. It is horrible and dangerous (and can cause crashes). The name tells you what the problem is. It is unsafe!!! There is no Swift equivalent because Swift has built-in memory management. This is one of the reasons why Swift is good. Don't worry be happy.
But do be careful, because this designation is warning you that if the delegate goes out of existence while the UITableView still exists, you will crash because the table view will not know this and may try to send a message to the non-existent delegate.
weak references don't seem to work in Swift unless a protocol is declared as #objc, which I don't want in a pure Swift app.
This code gives a compile error (weak cannot be applied to non-class type MyClassDelegate):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
I need to prefix the protocol with #objc, then it works.
Question: What is the 'pure' Swift way to accomplish a weak delegate?
You need to declare the type of the protocol as AnyObject.
protocol ProtocolNameDelegate: AnyObject {
// Protocol stuff goes here
}
class SomeClass {
weak var delegate: ProtocolNameDelegate?
}
Using AnyObject you say that only classes can conform to this protocol, whereas structs or enums can't.
Supplemental Answer
I was always confused about whether delegates should be weak or not. Recently I've learned more about delegates and when to use weak references, so let me add some supplemental points here for the sake of future viewers.
The purpose of using the weak keyword is to avoid strong reference cycles (retain cycles). Strong reference cycles happen when two class instances have strong references to each other. Their reference counts never go to zero so they never get deallocated.
You only need to use weak if the delegate is a class. Swift structs and enums are value types (their values are copied when a new instance is made), not reference types, so they don't make strong reference cycles.
weak references are always optional (otherwise you would used unowned) and always use var (not let) so that the optional can be set to nil when it is deallocated.
A parent class should naturally have a strong reference to its child classes and thus not use the weak keyword. When a child wants a reference to its parent, though, it should make it a weak reference by using the weak keyword.
weak should be used when you want a reference to a class that you don't own, not just for a child referencing its parent. When two non-hierarchical classes need to reference each other, choose one to be weak. The one you choose depends on the situation. See the answers to this question for more on this.
As a general rule, delegates should be marked as weak because most delegates are referencing classes that they do not own. This is definitely true when a child is using a delegate to communicate with a parent. Using a weak reference for the delegate is what the documentation recommends. (But see this, too.)
Protocols can be used for both reference types (classes) and value types (structs, enums). So in the likely case that you need to make a delegate weak, you have to make it an object-only protocol. The way to do that is to add AnyObject to the protocol's inheritance list. (In the past you did this using the class keyword, but AnyObject is preferred now.)
protocol MyClassDelegate: AnyObject {
// ...
}
class SomeClass {
weak var delegate: MyClassDelegate?
}
Further Study
Reading the following articles is what helped me to understand this much better. They also discuss related issues like the unowned keyword and the strong reference cycles that happen with closures.
Delegate documentation
Swift documentation: Automatic Reference Counting
"Weak, Strong, Unowned, Oh My!" - A Guide to References in Swift
Strong, Weak, and Unowned – Sorting out ARC and Swift
Related
How to make delegates in Swift
iOS: How To Make Weak Delegates In Swift
Swift delegation - when to use weak pointer on delegate
AnyObject is the official way to use a weak reference in Swift.
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate: AnyObject {
}
From Apple:
To prevent strong reference cycles, delegates should be declared as
weak references. For more information about weak references, see
Strong Reference Cycles Between Class Instances. Marking the protocol
as class-only will later allow you to declare that the delegate must
use a weak reference. You mark a protocol as being class-only by
inheriting from AnyObject, as discussed in Class-Only Protocols.
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
Update:
It looks like the manual has been updated and the example I was referring to has been removed. See the edit to #flainez's answer above.
Original:
Using #objc is the right way to do it even if you're not interoperating with Obj-C. It ensures that your protocol is being applied to a class and not an enum or struct. See "Checking for Protocol Conformance" in the manual.
The weak qualifier only applies to reference objects. Unless you add the #objc, AnyObject, or class qualifier on your protocol, the object conforming to the protocol might not be a reference object.
Thus you need on of those qualifiers (and AnyObject is recommended, since class is expected to be deprecated.)
By the way, note that adding #objc to your classes and properties is sometimes required, even in "pure Swift" applications. It doesn't have to do with you development language. It causes the compiler to build your code in a way that is compatible with the Objective-C runtime, which is required for some OS interfaces (target/action and old-style key paths for example)
protocol MyProtocol {
func doSomething()
}
class MyClass: MyProtocol {
func doSomething() {
print("Doing something")
}
}
var weakProtocol: Weak<MyProtocol>?
let myObject = MyClass()
weakProtocol = Weak(myObject)
weakProtocol?.doSomething() // Will print "Doing something"
protocol must be subClass of AnyObject, class
example given below
protocol NameOfProtocol: class {
// member of protocol
}
class ClassName: UIViewController {
weak var delegate: NameOfProtocol?
}
Apple uses "NSObjectProtocol" instead of "class".
public protocol UIScrollViewDelegate : NSObjectProtocol {
...
}
This also works for me and removed the errors I was seeing when trying to implement my own delegate pattern.