How do I check the class of an instance that conforms to a protocol in swift? - swift

I'm trying to check the class of an instance which conforms to a protocol.
I have a protocol.
protocol ToolbarProtocol {
func show()
func hide()
}
I have a class which conforms to that protocol.
class GameToolbar: ToolbarProtocol {
...
}
I have a manager class I createed to manage my toolbars.
class ToolbarManager {
var existingToolbars: [Game.rotation: Array<ToolbarProtocol>]
}
In this manager, I have a function that wants to find the first instance of a specific type of toolbar.
func getDebugToolbar() -> ToolbarProtocol? {
return existingToolbars[.east]?.first(where: { (toolbar: ToolbarProtocol) -> Bool in
toolbar.isKind(of: GameToolbar.self) //This line causes an error because .isKind is not a member of ToolbarProtocol
})
}
I can't call isKind(of) on toolbar, which previously worked when my toolbars were a different kind of class provided by an external library (which I'm trying to remove from my codebase because I want different functionality).
I tried making my protocol extend AnyObject, but I think that's implicit anyway, and it had no effect.
How can I check an array of instances which conform to a given protocl, to check for specific class types?

I think you would need to attempt to cast it, like
if let vc = toolbar as? GameToolbar {}
In your case, you might need something like this:
func getDebugToolbar() -> ToolbarProtocol? {
return existingToolbars[.east]?.first(where: { (toolbar: ToolbarProtocol) -> Bool in
let _ = toolbar as? GameToolbar
})
}

Related

How to implement custom implementation of method?

I'm drawing a blank for some reason.. If I want to make a bunch of objects from a class, but I want each instance to have its own unique implementation of a certain method, how would I do this?
For example:
class MyClass {
var name: String
func doSomething() {
// Each object would have custom implementation of this method, here.
}
}
Do I provide each object with its own closure during initialization, and then call that closure in the doSomething() method? I'm trying to figure out the correct or "Swiftly" way to do this. I'm also thinking along the lines of something with protocols, but I can't seem to figure out how to go about this.
I think there're many ways to do it.
In case of Base class + some sub-classes (e.g. Animal, subclassed by Dog, Cat, etc), you can do this:
First of all it's a good idea to define a protocol:
protocol MyProtocol {
func doSomething()
}
Also provide a default implementation, which throws a fatal error if a class doesn't override that method:
extension MyProtocol {
func doSomething() {
fatalError("You must override me")
}
}
Now your base class confirms the protocol thanks to default implementation. But it will throw a fatal error at runtime:
class MyClass: MyProtocol {
// conformant
}
Child class, however, will run correctly as long as it overrides this function:
class MyOtherClass: MyClass {
func doSomething() {
print("Doing it!")
}
}
You could also move fatal error into base class, and not do any extension implementation.
In case of many instances of the same Class, that solution makes no sense. You can use a very simple callback design:
typealias MyDelegate = () -> Void
class MyClass {
var delegate: MyDelegate?
func doSomething() {
delegate?()
}
}
let x = MyClass()
x.delegate = {
print("do it!")
}
x.doSomething()
// Or you can use a defined function
func doIt() {
print("also doing it")
}
x.delegate = doIt
x.doSomething()
It can also be that you re looking for Strategy pattern, or Template pattern. Depends on your usage details.
Do I provide each object with its own closure during initialization, and then call that closure in the doSomething() method
Yes. That is extremely common and eminently Swifty. Incredibly miminalistic example:
struct S {
let f:()->()
func doYourThing() { f() }
}
let s = S { print("hello") }
let s2 = S { print("goodbye" )}
s.doYourThing() // hello
s2.doYourThing() // goodbye
Giving an object a settable method instance property is very, very easy and common. It doesn't have to be provided during initialization — you might set this property later on, and a lot of built-in objects work that way too.
That, after all, is all you're doing when you create a data task with dataTask(with:completionHandler:). You are creating a data task and handing it a function which it stores, and which it will call when it has performed the actual networking.

Difference when declaring swift protocol using inheritance from another protocol or using where Self

I still don't understand what is the difference when declaring a Swift protocol using inheritance:
protocol SubProtocol: SuperProtocol { ... }
or using where Self
protocol SubProtocol where Self: SuperProtocol { ... }
By doing this on these two ways the results are exactly the same, both options compile fine, and it works, SubProtocol will have the same stuff than SuperProtocol has. So what is the difference?
The only difference I can see is the semantic, one is more clear than the other (see example below). But this is my point of view and I would like to know if someone else thinks the same, or perhaps I am miss-understanding the whole thing.
Example:
protocol Progressable {
var isInProgress: Bool { get }
}
protocol Downloadable: Progressable {
func download()
}
protocol ProgressReporting where Self: Progressable {
func reportProgress() -> Bool
}
For me, Downloadable makes sense it inherits from Progressable, every download is progressable, so that is fine.
But ProgressReporting not necessary needs to inherit from Progressable, for me it would make more sense to constraint it by using where, this way the reader can know that whoever implements it, will need to conform to Progressable too (see the comments on the code below), here is when I think the semantic is different.
class MyClassA: Downloadable {
var isInProgress: Bool { return true }
func download() {}
func foo() {
/*
I have access to `self.isInProgress` because this class conforms `Downloadable`
which inherits from `Progressable`, so this makes sense
*/
_ = self.isInProgress
}
}
class MyClassB: ProgressReporting {
var isInProgress: Bool { return true }
func reportProgress() {}
func foo() {
/*
I have access to `self.isInProgress` but according to `ProgressReporting` definition,
this class should be `Progressable` which is not, at least not explicitely
*/
_ = self.isInProgress
}
}
I would apreciate if someone can explain me what are the differences 🙂
Thanks in advance.
Speaking about Swift5, there is no difference between the two forms, see Swift 5 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)

Extending a class with instance method

I'm trying to extend the functionality of a existing type in Swift. I want to use dot syntax to call the methods on the type.
I want to say:
existingType.example.someMethod()
existingType.example.anotherMethod()
I'm currently using an extension like so:
extension ExistingType {
func someMethod() {
}
func anotherMethod() {
}
}
existingType.someMethod()
existingType.anotherMethod()
Doing this will expose too many functions. So, I want to write these methods in a class, and just extend the ExistingType to use an instance of the class. I'm not sure the right way to go about this.
if I were actually implementing the existing type, I would do the following:
struct ExistingType {
var example = Example()
}
struct Example {
func someMethod() {
}
func anotherMethod() {
}
}
Allowing me to call the methods by:
let existingType = ExistingType()
existingType.example.someMethod()
The issue is I'm not implementing the type, because it already exists. I just need to extend it.
It looks like you are trying to add another property example the existing class ExistingType and call methods of that property. You cannot add properties in extensions, though. The only way to add another property to the existing class is to subclass it.
You can create a new struct.
struct NewType {
let existingType: ExistingType
func someMethod() {
}
func anotherMethod() {
}
}

How can I call a static function on a protocol in a generic way?

Is there a point to declaring a static function on a protocol? The client using the protocol has to call the function on a type conforming to the protocol anyway right? That breaks the idea of not having to know the type conforming to the protocol IMO. Is there a way to call the static function on the protocol in a way where I don't have to know the actual type conforming to my protocol?
Nice question. Here is my humble point of view:
Is there a point to declaring a static function on a protocol?
Pretty much the same as having instance methods declared in a protocol.
The client using the protocol has to call the function on a type conforming to the protocol anyway right?
Yes, exactly like instance functions.
That breaks the idea of not having to know the type conforming to the protocol IMO.
Nope. Look at the following code:
protocol Feline {
var name: String { get }
static func createRandomFeline() -> Feline
init()
}
extension Feline {
static func createRandomFeline() -> Feline {
return arc4random_uniform(2) > 0 ? Tiger() : Leopard()
}
}
class Tiger: Feline {
let name = "Tiger"
required init() {}
}
class Leopard: Feline {
let name = "Leopard"
required init() {}
}
let feline: Feline = arc4random_uniform(2) > 0 ? Tiger() : Leopard()
let anotherFeline = feline.dynamicType.createRandomFeline()
I don't know the real type inside the variable feline. I just know that it does conform to Feline. However I am invoking a static protocol method.
Is there a better way to do this?
I see, you would like to call a static method/function declared in a protocol without creating a value that conforms to the protocol.
Something like this:
Feline.createRandomFeline() // DANGER: compiler is not happy now
Honestly I don't know the reason why this is not possible.
yes this is possible:
Swift 3
protocol Thing {
static func genericFunction()
}
//... in another file
var things:[Thing] = []
for thing in things {
type(of: thing).genericFunction()
}
Thank you #appzYourLife for the help! Your answer inspired my answer.
#appzYourLife answered my question. I had an underlying issue I was trying to resolve and the following code resolves my issue, so I'll post this here, maybe it helps someone with my same underlying question:
protocol MyProtocol {
static func aStaticFunc()
}
class SomeClassThatUsesMyProtocolButDoesntConformToIt {
var myProtocolType: MyProtocol.Type
init(protocolType: MyProtocol.Type) {
myProtocolType = protocolType
}
func aFunction() {
myProtocolType.aStaticFunc()
}
}
I created another solution for this case. IMHO this is quite clean and simple.
First, create a protocol for accessing instance type.
protocol TypeAccessible {
func type() -> Self.Type
}
extension TypeAccessible {
func type() -> Self.Type {
return Swift.type(of: self)
}
}
then create your concrete class as here. The point is your protocol should conform to TypeAccessible protocol.
protocol FooProtocol: TypeAccessible {
static func bar()
}
class Foo: FooProtocol {
static func bar() { }
}
On call site use it as
let instance: FooProtocol = Foo()
instance.type().bar()
For further use cases, just make sure your protocols conform to TypeAccessible and that's all.
A little late to the party on this one.
Here's my solution for "adding" static properties/functions/types to a protocol using typealias.
For example:
enum PropertyScope {
case all
case none
}
struct PropertyNotifications {
static var propertyDidChange =
Notification.Name("propertyDidChangeNotification")
}
protocol Property {
typealias Scope = PropertyScope
typealias Notifications = PropertyNotifications
var scope: Scope { get set }
}
Then you can do this anywhere in your code:
func postNotification() {
let scope: Property.Scope = .all
NotificationCenter.post(name: Property.Notifications.propertyDidChange,
object: scope)
}
Using protocols like Java interfaces is rarely a good idea. They are meta types, meant for defining contracts, which is an entirely different kind of thing.
That being said, just for the point of understanding, I find the most simple and effective way for creating the equivalent of a static factory method of a protocol to write a free function.
It should contain the protocol's name, hoping that that will prevent name clashes, and improve discoverability.
In other languages, createP would be a static member of P, named create and be called as P.create(...), which would drastically improve discoverability and guarantee to prevent name clashes.
In swift, though, this is not an option for protocols, so if protocols are for some reason really actually used as a replacement for interfaces, at least including the protocol's name in the function's name is an ugly workaround that's still slightly better than nothing.
P.S. in case the goal is actually to achieve something like an inheritance hierarchy with structs, union style enums are the tool that's meant to serve that purpose :)
protocol P
{
var x: Int { get }
}
func createP() -> P
{
if (todayIsMonday())
{
return A()
}
else
{
return B()
}
}
class A: P
{
var x = 5
}
class B: P
{
var x = 7
}
This isn't an answer so much as it is an extension to the question. Say I have:
#objc public protocol InteractivelyNameable: Nameable {
static func alertViewForNaming(completion:#escaping((_ success: Bool, _ didCancel: Bool, _ error: Error?) -> Void)) -> UIAlertController?
}
And I have a generic view controller that manages various types (generic type is .fetchableObjectType... basically NSFetchResult). I need to check if a specific object type conforms to the protocol, and if so, invoke it.
something like:
// valid swift code
if self.dataSource.fetchableObjectType is InteractivelyNameable {
// not valid swift code
if let alert = (self.dataSource.fetchableObjectType as InteractivelyNameable).alertViewForNaming(....)
}
I had a situation where I need to create same DomainModel object from 2 different response. so this (static method in protocol helped me) approach helped me.
protocol BaseResponseKeyList: CodingKey {
static func getNameKey()->Self
}
enum FirstResponseKeyList: String, BaseResponseKeyList {
case name
func getNameKey()->FirstResponseKeyList {
return .name
}
}
enum SecondResponseKeyList: String, BaseResponseKeyList {
case userName
func getNameKey()->SecondResponseKeyList {
return .userName
}
}
struct MyDomainModel<T:BaseResponseKeyList> : Decodable {
var name:String?
required init(from d:Decoder) {
do {
let container = try d.container(keyedBy:T.self)
name = try container.decode(String.self, forKey:T.getNameKey())
}catch(_) {
print("error")
}
}
}
let myDomainModel = try JSONDecoder().decode(MyDomainModel <FirstResponseKeyList>.self, from: data)
let myDomainModel2 = try JSONDecoder().decode(MyDomainModel <SecondResponseKeyList>.self, from: data2)

A way to inherit from multiple classes

I have two classes I want to use in my new class. The first one implements a swipe to delete and the second enables a long press gesture:
class DeleteItem: UITableViewCell {
}
class OpenDetail: UITableViewCell {
}
Since Swift doesn't allow a class to inherit from multiple classes the following example obviously won't work:
class ItemViewCell: DeleteItem, OpenDetail {
}
So in order to create ItemViewCell and having both options, I'll have to have one of the classes to inherit from each other:
class DeleteItem: UITableViewCell {
}
class OpenDetail: DeleteItem {
}
class ItemViewCell: OpenDetail {
}
The problem is, if I only want the long press gesture I'll have to create a new class without inheriting from DeleteItem. Is there a better way of doing this?
This is the perfect case for using Protocols and Protocol extension. A swift protocol is like an interface in Java for example. A protocol can define a set of functions which has to be implemented by the entities which want to conform to this protocol, moreover a protocol can define properties which has to be present in these entities too. For example:
protocol ItemDeleter {
var deletedCount: Int {get set}
func deleteItem(item: ItemType)
}
The problem is, that each entity would have to provide its own implementation of func deleteItem(item: ItemType) even if multiple entities share the same logic of deleting an item, this where a protocol extension comes in handy. For example:
extension ItemDeleter {
func deleteItem(item: ItemType) {
// logic needed to delete an item
// maybe incremented deletedCount too
deletedCount++
}
}
Then you could make your ItemViewCell conform to the ItemDeleter protocol, in this case all you need is to make sure that ItemViewCell has a property deletedCount: Int. It does not need to provide an implementation for func deleteItem(item: ItemType) as the protocol itself provides a default implementation for this function, however you can override it in your class, and the new implementation will be used. The same applies for DetailOpener protocol.