I have a class, SlideAnimationController, that is a subclass of NSObject should conform to the UIViewControllerAnimatedTransitioning protocol.
In Xcode 6 GM, I get the error message that my class does not conform to the protocol.
I have implemented transitionDuration and animateTransition. These are the only two required methods of the three that the protocol calls for.
Adding the last method, animationEnded, does not make any difference.
What am I missing? This same code was functional not too long ago.
Edit
Here is the class implementation:
import UIKit
class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
var fromIndex: Int = 0
var toIndex: Int = 0
func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval {
return 1
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning!) {
//Stuff
}
}
This bug has to do with changes to Swift's versions of Objective-C API's. In many cases where Swift had implicitly unwrapped optionals as arguments, the arguments have been changed to either normal or optional variables.
Normally, when overriding a method, Xcode offers a fix-me to correct these uses of ! where they are no longer needed.
However, since these methods I declared are not necessarily part of the protocol, Xcode recognizes these methods, just does not realize that those are the ones I want for the protocol.
In order to fix this, I needed to remove the !'s from both method parameters (e.g. UIViewControllerContextTransitioning! becomes UIViewControllerContextTransitioning)
Related
In addition to this syntax with a protocol extension:
protocol P {}
extension P where Self : UIView {}
... I discovered by accident that you can use the same where clause on the protocol itself:
protocol P where Self : UIView {}
Notice that this is not the same as a where clause constraining a generic protocol, and does not itself make P a generic protocol.
My experiments seem to show that only a colon can be used here, and the thing after the colon must be a class or a protocol (which may be generic).
I became curious: how did this escape my notice? So I went hunting for evidence of when it arose. In Swift 3.0, the former syntax is legal but not the latter. In Swift 3.3, both are legal. So the latter syntax must have been quietly introduced in something like Swift 3.2. I say "quietly" because I can't find anything about it in the release notes.
What is the second syntax for? Is it, as it appears, just a convenient way of making sure no other type can adopt this protocol? The Swift headers do not seem to make any use of it.
The ability to put superclass constraints on protocols declarations (that is, being able to define protocol P where Self : C where C is the type of a class) was a premature consequence of SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x can cause miscompilation and crashes, so I would avoid using it until Swift 5.
In Swift 5 (Xcode 10.2) the feature has now been implemented. From the release notes:
Protocols can now constrain their conforming types to those that
subclass a given class. Two equivalent forms are supported:
protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ }
Swift 4.2 accepted the second form, but it wasn’t fully implemented
and could sometimes crash at compile time or runtime. (SR-5581)
(38077232)
This syntax places a superclass constraint on MyView which restricts conforming types to those inheriting from (or being) UIView. In addition, the usage of MyView is semantically equivalent to a class existential (e.g UIView & MyView) in that you can access both members of the class and requirements of the protocol on the value.
For example, expanding upon the release notes' example:
protocol MyView : UIView {
var foo: Int { get }
}
class C : MyView {} // error: 'P' requires that 'C' inherit from 'UIView'
class CustomView : UIView, MyView {
var foo: Int = 0
}
// ...
let myView: MyView = CustomView(frame: .zero)
// We can access both `UIView` members on a `MyView` value
print(myView.backgroundColor as Any)
// ... and `MyView` members as usual.
print(myView.foo)
In addition to this syntax with a protocol extension:
protocol P {}
extension P where Self : UIView {}
... I discovered by accident that you can use the same where clause on the protocol itself:
protocol P where Self : UIView {}
Notice that this is not the same as a where clause constraining a generic protocol, and does not itself make P a generic protocol.
My experiments seem to show that only a colon can be used here, and the thing after the colon must be a class or a protocol (which may be generic).
I became curious: how did this escape my notice? So I went hunting for evidence of when it arose. In Swift 3.0, the former syntax is legal but not the latter. In Swift 3.3, both are legal. So the latter syntax must have been quietly introduced in something like Swift 3.2. I say "quietly" because I can't find anything about it in the release notes.
What is the second syntax for? Is it, as it appears, just a convenient way of making sure no other type can adopt this protocol? The Swift headers do not seem to make any use of it.
The ability to put superclass constraints on protocols declarations (that is, being able to define protocol P where Self : C where C is the type of a class) was a premature consequence of SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x can cause miscompilation and crashes, so I would avoid using it until Swift 5.
In Swift 5 (Xcode 10.2) the feature has now been implemented. From the release notes:
Protocols can now constrain their conforming types to those that
subclass a given class. Two equivalent forms are supported:
protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ }
Swift 4.2 accepted the second form, but it wasn’t fully implemented
and could sometimes crash at compile time or runtime. (SR-5581)
(38077232)
This syntax places a superclass constraint on MyView which restricts conforming types to those inheriting from (or being) UIView. In addition, the usage of MyView is semantically equivalent to a class existential (e.g UIView & MyView) in that you can access both members of the class and requirements of the protocol on the value.
For example, expanding upon the release notes' example:
protocol MyView : UIView {
var foo: Int { get }
}
class C : MyView {} // error: 'P' requires that 'C' inherit from 'UIView'
class CustomView : UIView, MyView {
var foo: Int = 0
}
// ...
let myView: MyView = CustomView(frame: .zero)
// We can access both `UIView` members on a `MyView` value
print(myView.backgroundColor as Any)
// ... and `MyView` members as usual.
print(myView.foo)
How can I provide default implementations for Objective-C optional protocol methods?
Ex.
extension AVSpeechSynthesizerDelegate {
func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) {
print(">>> did finish")
}
}
Expectation: Whatever class that conforms to AVSpeechSynthesizerDelegate should run the above function whenever a speech utterance finishes.
You do it just exactly as you've implemented it. The difference ends up being in how the method is actually called.
Let's take this very simplified example:
#objc protocol FooProtocol {
optional func bar() -> Int
}
class Omitted: NSObject, FooProtocol {}
class Implemented: NSObject, FooProtocol {
func bar() -> Int {
print("did custom bar")
return 1
}
}
By adding no other code, I'd expect to have to use this code as such:
let o: FooProtocol = Omitted()
let oN = o.bar?()
let i: FooProtocol = Implemented()
let iN = i.bar?()
Where oN and iN both end up having type Int?, oN is nil, iN is 1 and we see the text "did custom bar" print.
Importantly, not the optionally chained method call: bar?(), that question mark between the method name in the parenthesis. This is how we must call optional protocol methods from Swift.
Now let's add an extension for our protocol:
extension FooProtocol {
func bar() -> Int {
print("did bar")
return 0
}
}
If we stick to our original code, where we optionally chain the method calls, there is no change in behavior:
However, with the protocol extension, we no longer have to optionally unwrap. We can take the optional unwrapping out, and the extension is called:
The unfortunate problem here is that this isn't necessarily particularly useful, is it? Now we're just calling the method implemented in the extension every time.
So there's one slightly better option if you're in control of the class making use of the protocol and calling the methods. You can check whether or not the class responds to the selector:
let i: FooProtocol = Implemented()
if i.respondsToSelector("bar") {
i.bar?()
}
else {
i.bar()
}
This also means you have to modify your protocol declaration:
#objc protocol FooProtocol: NSObjectProtocol
Adding NSObjectProtocol allows us to call respondsToSelector, and doesn't really change our protocol at all. We'd already have to be inheriting from NSObject in order to implement a protocol marked as #objc.
Of course, with all this said, any Objective-C code isn't going to be able to perform this logic on your Swift types and presumably won't be able to actually call methods implemented in these protocol extensions it seems. So if you're trying to get something out of Apple's frameworks to call the extension method, it seems you're out of luck. It also seems that even if you're trying to call one or the other in Swift, if it's a protocol method mark as optional, there's not a very great solution.
Both this declaration
protocol SomeProtocol : AnyObject {
}
and this declaration
protocol SomeProtocol : class {
}
seem to make it so that only classes can conform to this protocol (i.e. that the instances of the protocol are references to objects), and have no other effects.
Is there any difference between them? Should one be preferred over the other? If not, why is there two ways to do the same thing?
I am using the latest released Xcode 6.3.1.
This was answered by an official Swift developer (Slava_Pestov) on the Swift forums. Here is the summary:
You should use AnyObject (protocol SomeProtocol: AnyObject).
AnyObject and class are equivalent. There is no difference.
class will eventually be deprecated.
Regarding the answer https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4, this answer is deprecated. These words are the same now.
DEPRECATED
Update: After consulting with the powers that be, the two definitions are supposed to be equivalent, with AnyObject being used as a stand-in while class was being finished. In the future the latter will obviate the former but, for now, they do present a few minor differences.
The difference lies in the semantics of #objc declarations. With AnyObject, the expectation is that conforming classes may or may not be proper Objective-C objects, but the language treats them as such anyway (in that you lose static dispatch sometimes). The takeaway from this is that you can treat an AnyObject et al. protocol constraint as a way to ask for #objc member functions as shown in the example in documentation for AnyObject in the STL:
import Foundation
class C {
#objc func getCValue() -> Int { return 42 }
}
// If x has a method #objc getValue()->Int, call it and
// return the result. Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
if let f: ()->Int = x.getCValue { // <===
return f()
}
return nil
}
// A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
return x.getCValue?() // <===
}
// An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}
The same example falls over immediately if you change that to a class-deriving protocol:
import Foundation
protocol SomeClass : class {}
class C : SomeClass {
#objc func getCValue() -> Int { return 42 }
}
// If x has a method #objc getValue()->Int, call it and
// return the result. Otherwise, return nil.
func getCValue1(x: SomeClass) -> Int? {
if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue'
return f()
}
return nil
}
// A more idiomatic implementation using "optional chaining"
func getCValue2(x: SomeClass) -> Int? {
return x.getCValue?() // <=== SomeClass has no member 'getCValue'
}
// An implementation that assumes the required method is present
func getCValue3(x: SomeClass) -> Int { // <===
return x.getCValue() // <=== SomeClass has no member 'getCValue'
}
So it seems class is a more conservative version of AnyObject that should be used when you only care about reference semantics and not about dynamic member lookups or Objective-C bridging.
In the Swift programming language guide for protocols, under the Class-Only Protocols section. It only mentioned AnyObject, but not class.
You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
For that reason, I will suggest using AnyObject over class for new code or new project. Other than that, I don't see any obvious difference between them.
From 2021, Xcode 12.5, Big Sur OS:
Usage of class is deprecated by apple.
Use AnyObject instead.
Happy Coding.
AnyObject is a protocol to which all classes implicitly conform (source). So I would say there is no difference: you can use either to require class constraint.
If you open the help (alt-click) in Xcode 9 for class in a line such as protocol P: class {}, you will get typealias AnyObject.
Thus, the code compiled (in Swift 4) will be the same whether you constrain the protocol to class or AnyObject.
That said, there is also the question of style and future options — a future Swift version might want to treat class and AnyObject differently in some subtle way, even if that is not the case right now.
(Edit: This has finally happened in Swift 5.4/Xcode 12.5.)
I misspoke before. #MartinR should really answer this, since he's the one who corrected me and provided the correct information.
The real difference is that a protocol with the class qualifier can only be applied to a class, not a struct or enum.
Martin, why don't you answer and the OP can accept your answer?
I have a Swift class called Helpers defined as follows:
class Helpers : NSObject {
class func sayValue(value:Printable) {
println(value)
}
}
I am trying to use this in an Objective-C .m file, like so:
[Helpers sayValue:#"Hello"];
But the compiler is complaining with the error: No known class method for selector 'sayValue:'
However if I change the sayValue to have a strict type, it works fine:
class Helpers : NSObject {
class func sayValue(value:String) {
println(value)
}
}
What's going on here?
You've already figured it out. Swift protocols don't map as types into Objective-C.
Always just ask yourself "Could I say this in Objective-C?" You can't say this in Objective-C:
+ (void) sayValue: (Printable*) value { ... }
That's illegal, because Printable (a protocol) isn't a type. So your Swift function defined that way doesn't magically map upward into Objective-C, as it has nothing to map to. It is filtered out, and Objective-C never sees it.
What I'm finding is that all this works remarkably cleanly. I was afraid that a Swift class that uses any non-Objective-C features wouldn't map to an Objective-C class at all. But, on the contrary, you can use all the pure-Swift features you like, and they simply don't map up into Objective-C: they are cleanly filtered out, and those parts of your Swift class that do map into Objective-C work just fine from Objective-C. It's quite brilliant.
You are free to define a protocol that maps as a type for purposes of, say, defining a delegate. But to do that, you must expose the protocol using #objc. For example, from one of my apps:
#objc protocol ColorPickerDelegate {
func colorPicker (/*...*/)
}
class ColorPickerController : UIViewController {
weak var delegate: ColorPickerDelegate?
// ...
}
You can't talk that way unless the protocol is #objc. Now Objective-C understands the type of delegate to mean id<ColorPickerDelegate> and you're in business.
(So you could probably talk the way you're suggesting by defining an #objc protocol MyPrintable which does nothing but adopt Printable; I haven't tried it, however, so that's just a conjecture.)