Swift - Property with type and protocol - ios

In one of my Objective-C clases, I have a property of type UIViewController<UIProfileListHeaderDelegate>, how would I represent this in Swift? I need to access properties and methods from both UIViewController and UIProfileListHeaderDelegate.
Thanks!

The swift way to handle this is to define a protocol that includes the relevant methods from UIViewController and have your UIProfileListHeaderDelegate inherit from that.
Define a protocol with the methods you care about:
protocol ViewControllerSubset {
var view:UIView!
}
Declare that UIViewController implements the protocol, don't need to actually implement anything because it's already there
extension UIViewController : ViewControllerSubset {}
Inherit your protocol from that
protocol UIProfileListHeaderDelegate : ViewControllerSubset
And away you go.
If you don't want to change the hierarchy of your protocol (or can't because it's a system protocol) you can define a protocol that contains both protocols)
protocol EquatableAndComparable : Equatable, Comparable { }

Related

Swift cast object to type and protocol at the same time

How can I cast a given object to a type and a protocol in order to call some methods that are defined as an extension
For Example:
extension Identifiable where Self: NSManagedObject, Self: JsonParseDescriptor {
func someMethod() { }
}
Now I have an object that I retrieved from Core data and I would like to cast it to the above protocols in order to call someMethod on it. I could cast to the protocols using protocol<Identifiable, JsonParseDescriptor> , but how can I include the NSManagedObejct type in it also?
Thanks
As of Swift 4, it is now possible to make mentioned cast directly without tricky workarounds. The task is accomplished similarly as we do protocol composition:
var myVar = otherVar as! (Type & Protocol)
No more need for extensions and bridge protocols.
What you're looking for it called a concrete same-type requirement. Unfortunately, it's not yet possible in Swift.
See ticket SR-1009 and SR-1447 for details. You should also checkout this answer.
In the mean-while, you can extend NSManagedObject with a dummy protocol with the methods you need:
protocol _NSManagedObject {
//the methods you want
}
extension NSManagedObject: _NSManagedObject {}
extension Identifiable where Self: _NSManagedObject, Self: JsonParseDescriptor {
func someMethod() { }
}

How to specify multiple type for delegate reference?

I have two problems in swift
1. Specifying multiple type for a delegate
2. Specifying a type for a delegate
id<MyProtocol, MyAnotherProtocol> delegate;
UIViewController<MyProtocol> *delegate;
How do I convert these two line in swift?
I searched the internet and tried to look into the library code so that I can get the hint, but didn't get anything.
Use protocol:
var delegate: protocol<MyProtocol, MyAnotherProtocol>
For second one you can use just:
var delegate: MyProtocol
You can use protocol composition to combine multiple protocols in single name as below.
// Protocol Composition!!
typealias MyCompositeProtocol = protocol< MyProtocol, MyAnotherProtocol >
Then you can use the name MyCompositeProtocol instead of specifying multiple names.
like below,
class DetailsViewController: UIViewController, MyCompositeProtocol {
var myDelegate : MyCompositeProtocol?
}

How to create an array of objects of a specific type, conforming to a protocol in Swift 2

My question is simple and hopefully just a matter of syntax. I'm trying to create an array of UIViewControllers which conform to my protocol. I am able to create this requirement as a function parameter:
func doSomething<T: UIViewController where T: MyProtocol>(controller: T) { ... }
Now, I'd like to store those objects in an array, I was hoping I could have something like:
var viewControllers = Array<T: UIViewController where T: MyProtocol>()
However, I can't figure out how to create this constraint on an array. Is this possible or am I going about it the wrong way?
Your best bet is probably to use a protocol that only your class conforms to and use this one to constrain your type:
protocol ClassProtocol {}
class Class : ClassProtocol {}
protocol Protocol {}
class SubClass : Class, Protocol {}
let x : protocol<ClassProtocol, Protocol> = SubClass()
The Foundation framework does this too with NSObject and NSObjectProtocol

How can I create a Set of delegate protocol items in Swift?

Let's assume I have five UIView objects which all conform to a particular protocol. I have an object which should maintain a list of these objects, and message them all when necessary.
protocol MyProtocol: AnyObject {
func doSomething()
}
The problem is, when I go to add these UIViews to a Set variable, the compiler produces an error because MyProtocol does not conform to Hashable. I can understand the reasoning for this, can anyone think of good ways to overcome this? In the meantime I considered using NSHashTable instead, but you lose the nice enumeration features of Sets.
Updating answer to post some sample code (this is still not working)
protocol MyProtocol: class, AnyObject {
func doSomething()
}
class MyClass {
var observers: Set<MyProtocol> = Set<MyProtocol>()
}
As you are defining protocol for class so you need to write 'class' keyword before inheriting any other protocol:
protocol MyProtocol: AnyObject, Hashable{
func doSomething()
}
class MyClass<T: MyProtocol> {
var observers: Set<T> = Set<T>()
}
Change your protocol to this and it will work fine.
You can refer Apple Documentation for further details.

Swift Declare Class Func in Protocol

I had following confusion. As far as I know the main difference between static and class keywords when declaring method is that the second one could be overridden in subclasses.
The problem
However when I declare a protocol in Swift 1.2 like this:
protocol MyProtocol
{
class func dummyClassMethod()
}
compiler gives an error:
Class methods are only allowed within classes; use 'static' to declare
a static method
The error is pretty descriptive as obviously MyProtocol is not a class, however I want to make a class func part of the protocol.
What I've tried
I've found that if I declare interface in protocol as static, compiler is happy and I could use this static method in all classes that adopt this protocol:
protocol MyProtocol
{
static func dummyClassMethod()
}
The question
So my question basically is is this right? This declaration states that my class method cannot be overridden in children, however in my implementation I could write and use the following:
class ClassA: MyProtocol
{
class func dummyClassMethod() {
}
}
class ClassB: ClassA
{
override class func dummyClassMethod() {
}
}
and now my dummyClassMethod is not static anymore...
Compiler is Ok and everything works - but why?
Is it specific to the fact that interface itself is static, however
it's implementation is not?
Is there a better alternative for class func in protocols?
Objective-C solution
In ObjC this is pretty easy and compile & run flawlessly:
#protocol MyProtocol
+(void)dummyClassMethod;
#end
You can review Apple's Documentation (subsection Method Requirements).
There says:
As with type property requirements, you always prefix type method requirements with the static keyword when they are defined in a protocol. This is true even though type method requirements are prefixed with the class or static keyword when implemented by a class
In practice, You can do it as follow:
First, declare your protocol:
protocol SomeProtocol {
static func someMethod()
}
Then, in your class you've 2 options:
First:
class SomeClass : SomeProtocol {
class func someMethod()
}
Second:
class SomeClass : SomeProtocol {
static func someMethod()
}
I hope, this may clarify your doubt..
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
A protocol defines a blueprint of methods, properties, and other
requirements that suit a particular task or piece of functionality.
The protocol doesn’t actually provide an implementation for any of
these requirements—it only describes what an implementation will look
like. The protocol can then be adopted by a class, structure, or
enumeration to provide an actual implementation of those requirements.
After this protocol definition it becomes reasonable that
As with type property requirements, you always prefix type method
requirements with the static keyword when they are defined in a
protocol. This is true even though type method requirements are
prefixed with the class or static keyword when implemented by a class...
To make protocol method static and final implement that method with static keyword
class ClassA: MyProtocol{
static func dummyClassMethod() {
}
}
and now you cant override dummyClassMethod function anymore. If you want to prevent overriding only you must declare protocol method as final. About class functions, they were not fully supported in Swift 1.0 and now in Swift 1.2 I think that they are moving towards static functions

Resources