How to represent an optional Bool (Bool?) in Objective-C? - swift

I am trying to write a protocol in swift
#objc protocol RestAPIManagerDelegate {
optional func credentialValidated(isValid: Bool?)
}
But I am getting following error:
'Method cannot be marked #objc because the type of the parameter cannot be represented in Objective-C'
Any suggestion?

The problem is this type declaration:
`isValid: Bool?`
That is perfectly fine in Swift. But you cannot expose it to Objective-C, because Objective-C does not have any notion of an Optional BOOL - a BOOL in Objective-C is basically just a number, a primitive C datatype (what we call a scalar).
Here's another way of looking at it. In an interchange with Objective-C, you can use a Swift Optional anywhere that Objective-C can say nil - indeed, to a large extent Swift Optional exists exactly in order to deal with the possibility that Objective-C will say nil or that you might need to say nil to Objective-C. But a BOOL in Objective-C can never be nil - it can only be YES or NO (Swift true or false).
So you have three choices:
Take away the #objc that exposes all this to Objective-C
Remove the Optional and just declare that type a Bool
Use an object type. For example, declare the type as AnyObject? (or NSNumber?). This will work because Swift will bridge a Bool to an NSNumber (including as it passes into an AnyObject), and Objective-C will deal just fine with an Optional AnyObject or Optional NSNumber because those are object types, not scalars.

Object-C does not have the concept of optionals, try to remove the "?" from your declaration

It's OK to use NSNumber? instead, but there is another way.
You can create OptionalBool enum and use it instead of Bool? for compatibility with Objective-C.
Creating OptionalBool enum in Swift code:
#objc enum OptionalBool: Int {
case none
case yes
case no
}
#objc protocol RestAPIManagerDelegate {
#objc optional func credentialValidated(isValid: OptionalBool)
}
Using OptionalBool in Objective-C code:
#interface RestAPIManagerHandler () <RestAPIManagerDelegate>
#end
#implementation RestAPIManagerHandler
- (void)credentialValidatedWithIsValid:(enum OptionalBool)isValid {
switch (isValid) {
case OptionalBoolYes:
NSLog(#"TRUE");
break;
case OptionalBoolNo:
NSLog(#"FALSE");
break;
case OptionalBoolNone:
NSLog(#"NULL");
break;
}
}
#end

Swift Bool are converted in NSNumber so for example if a Swift method returns [Bool] and if you receive this array in Objective-C code, it become a NSArray <NSNumber *>. And if you give this array to a Swift method which receives a [Bool] as parameter, the conversion will be done automatically.

If you are wanting to just do a protocol in Swift, for use within Swift, without optionals you can do this:
public protocol Note {
var content: [ContentType] {get}
func insertNote(note: Note) -> Bool
}
That will force a class to implement a method that returns a Bool and have an array of some class called ContentType.
If you want to make the method optional, you must specify the objc keyword as you have done, regardless if you are interoperating with Objective-C or not. At that point, everything else should work in your example.
#objc protocol RestAPIManagerDelegate {
optional func credentialValidated(isValid: Bool?)
}
From Apples documentation:
Optional protocol requirements can only be specified if your protocol is marked with the #objc attribute.
This attribute indicates that the protocol should be exposed to Objective-C code and is described in Using Swift with Cocoa and Objective-C. Even if you are not interoperating with Objective-C, you need to mark your protocols with the #objc attribute if you want to specify optional requirements.
Note also that #objc protocols can be adopted only by classes, and not by structures or enumerations. If you mark your protocol as #objc in order to specify optional requirements, you will only be able to apply that protocol to class types.
The example given by Apple:
#objc protocol CounterDataSource {
optional func incrementForCount(count: Int) -> Int
optional var fixedIncrement: Int { get }
}

Related

Conform to a protocol misunderstanding

class SuperDelegate <T: AnyObject> {
func addDelegate(delegate: T)
{
}
}
My question is about T key, does it mean the same as id in Objective-c? I mean about case of uses.
how to understand the first line class SuperDelegate <T: AnyObject> Sorry I am new in Swift.
As Objective C program for me this line means that we make class to conform a protocol that has to implement all required method. But I don't understand func addDelegate(delegate: T) is this the same like
- (void)addDelegate:(id)delegate which is a property id <T> delegate.
Yes you are correct in your assumptions that AnyObject behaves like id:
You can call any Objective-C method and access any property on an
AnyObject value without casting to a more specific class type. This
includes Objective-C compatible methods and properties marked with the
#objc attribute.
but you have used it here as a generic type rather than as a concrete type that should be cast to. The class is requiring a type that adheres to the AnyObject protocol but it isn't forcing it to be AnyObject (see header files: cmd + click on AnyObject inside Xcode).
So your instance could be instantiated SuperDelegate<AnyObject> but it could also be instantiated SuperDelegate<NSDate>. This means that the whole subset of ObjC methods and properties cannot be guaranteed as they can with a cast to AnyObject as a concrete type because at runtime T might represent NSDate or NSNumber or any other class.
To achieve what you want you would need to write:
class SuperDelegate {
func addDelegate(delegate: AnyObject)
{
}
}
But Swift is a strongly-typed language and it would normally be the case that you had a delegate protocol and that the delegate for your type adhered to the delegate protocol:
protocol DelegateProtocol {
func somethingHappened()
}
struct MyTypeDelegate:DelegateProtocol {
func somethingHappened() {
print("Thanks for telling me!")
}
}
struct MyType {
var delegate:DelegateProtocol?
func tellDelegateSomethingHappened() {
delegate?.somethingHappened()
}
}
let del = MyTypeDelegate()
var type = MyType()
type.delegate = del
type.tellDelegateSomethingHappened()

Read-only properties of protocols in Swift

From the "Learn the Essentials of Swift" playground, there's an example protocol:
protocol ExampleProtocol {
var simpleDescription: String { get }
func adjust()
}
There's a short passage after this example that reads:
Note: The { get } following the simpleDescription property indicates that it is read-only, meaning that the value of the property can be viewed, but never changed.
Additionally an example is given of a class conforming to this protocol:
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
However how does this class conform to the protocol? What's stopping me from mutating simpleDescription? What don't I understand?
There's no way to specify in a protocol that you must have a read-only property. Your protocol asks for a simpleDescription property, and allows but does not require a setter.
Note also that the only reason you may mutate simpleDescription is because you know your a is of type SimpleClass. If we have a variable of type ExampleProtocol instead...
var a: ExampleProtocol = SimpleClass()
a.simpleDescription = "newValue" //Not allowed!
Protocols place requirements on object's interface, but do not restrict implementation from providing more operations than that.
In this example, the protocol requires a readable simpleDescription property and adjust() method. The class provides that, so it conforms to the protocol. In other words, this protocol says implementation must have get operation, but it does not prohibit them from also having set.
You will not be able to mutate simpleDescription via that protocol interface, because it does not provide such operation, but nothing prevents you from mutating it through different interface — in this example, the interface of the implementing class.
Found this and thought it may be of interest in addition to the excellent answer already provided:
If a protocol requires a property to be gettable and settable, that property requirement cannot be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it is valid for the property to be also settable if this is useful for your own code.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2).” iBooks. https://itun.es/us/jEUH0.l

What's the difference between a protocol extended from AnyObject and a class-only protocol?

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?

Swift alternative to respondsToSelector:

I was trying to implement swift's alternative to the respondsToSelector: syntax that was also shown in the keynote.
I have the following:
protocol CustomItemTableViewCellDelegate {
func changeCount(sender: UITableViewCell, change: Int)
}
and then later in the code I call
class CustomItemTableViewCell: UITableViewCell {
var delegate: CustomItemTableViewCellDelegate
...
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
...
delegate?.changeCount?(self, change: -1)
}
...
}
I get the following errors
Operand of postfix '?' should have optional type; type is
'(UITableViewCell, change:Int) -> ()'
Operand of postfix '?' should
have optional type; type is 'CustomItemTableViewCellDelegate'
Partial application of protocol method is not allowed
What I am doing wrong?
Thanks
You have two ? operators, and they're both causing problems.
First, the one after delegate indicates that you want to unwrap an optional value, but your delegate property isn't declared that way. It should be:
var delegate: CustomItemTableViewCellDelegate?
Second, it looks like you want your changeCount protocol method to be optional. If you do, you need to both mark the protocol with the #objc attribute and mark the function with the optional attribute:
#objc protocol CustomItemTableViewCellDelegate {
optional func changeCount(sender: UITableViewCell, change: Int)
}
(Note: Classes that conform to #objc protocols need to be #objc themselves. In this case you're subclassing an Objective-C class, so you're covered, but a new class would need to be marked with the #objc attribute.)
If you only want the delegate to be optional (that is, it's okay to not have a delegate, but all delegates need to implement changeCount), then leave your protocol as is and change that method call to:
delegate?.changeCount(self, change: -1)
The error says it all.
You use ? on an explicit type, it can't be nil, so simply don't use ? on that variable.
If you have a var like this one
var changeCount: Int
or this
var changeCount = 3
You have an explicit type. When an explicit type is requested, then you should give an explicit type, which is changeCount and not changeCount?.
If you want optional variable to begin with, declare it with an ?:
var changeCount: Int?
You can't use literal syntax with optional type if the type should be implicit. Because 3 is always explicit Int if not stated otherwise.

Check if a func exists in Swift

I wish to check if a func exists before I call it. For example:
if let touch: AnyObject = touches.anyObject() {
let location = touch.locationInView(self)
touchMoved(Int(location.x), Int(location.y))
}
I would like to call touchMoved(Int, Int) if it exists. Is it possible?
You can use the optional chaining operator:
This seems to only work with ObjC protocols that have #optional functions defined. Also seems to require a cast to AnyObject:
import Cocoa
#objc protocol SomeRandomProtocol {
#optional func aRandomFunction() -> String
#optional func anotherRandomFunction() -> String
}
class SomeRandomClass : NSObject {
func aRandomFunction() -> String {
return "aRandomFunc"
}
}
var instance = SomeRandomClass()
(instance as AnyObject).aRandomFunction?() //Returns "aRandomFunc"
(instance as AnyObject).anotherRandomFunction?() //Returns nil, as it is not implemented
Whats weird is that in the example above, the protocol "SomeRandomProtocol" is not even declared for "SomeRandomClass"... yet without the protocol definition, the chaining operator gives an error-- in the playground at least. Seems like the compiler needs a prototype of the function declared previously for the ?() operator to work.
Seems like maybe there's some bugs or work to do there.
See the "swift interoperability in depth" session for more info on the optional chaining operator and how it works in this case.