passing data to already implemented delegate methods inside extensions inside swift - ios

I am trying to pass data to a delegate method implemented inside an extension but i am unable to do it since extensions cannot have stored properties. How to get it done?

You can make the stored property a requirement of the delegate protocol.
protocol MyProtocol {
var aProperty: String { get set }
func aProtocolMethod()
}
For the corresponding extension of MyProtocol, the property can be accessed directly.
extension MyProtocol {
func aProtocolMethod() {
print("property:" + aProperty)
}
}
In the class which conforms to MyProtocol, it should implement the variable to store data.
class MyClass: MyProtocol {
var aProperty: String
init() {
self.aProperty = "some value"
}
}
let myClass = MyClass()
myClass.aProtocolMethod()

Related

How to extend default implementation (with an extension) adding a didSet on a property?

How can I implement didSet on MyProtocol var through an extension?
I need to run some specific code after it has been set.
I tried this, but I get this error:
Extensions may not contain stored properties
protocol MyProtocol {
var contact: MyContact? { get set }
}
extension MyProtocol {
var contact: MyContact? {
didSet {
// some code
}
}
}
From the docs:
Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID151
If you want to set a default value of contact, then it has to be a computed property.
extension MyProtocol {
var contact: MyContact? {
return MyContact()
}
}

Swift cast AnyObject to protocol and assign property

I am trying to solve a dependency in Swift using an external injector like this:
class DependencyInjector {
var networkManager:NetworkQueueManager
protocol InjectorDelegateNetworkQueue{
var networkManager:NetworkQueueManager {get set}
}
func injectDependencies(object:AnyObject){
if object is InjectorDelegateNetworkQueue{
object.networkManager = networkManager
}
}
}
Obviously, this won't work since AnyObject does not have a property called networkManager, only the cast object has one.
I mean to call this method inside the init method of other classes, by calling
DependencyInjector.sharedInstance().injectDependencies(self)
How can I get this to work in Swift?
can maybe go like:
func injectDependencies(object:AnyObject){
var thing:InjectorDelegateNetworkQueue? = object as? InjectorDelegateNetworkQueue
if thing {
thing.networkManager = networkManager
}
}
Change your func to this.
func injectDependencies(object:AnyObject){
if object is InjectorDelegateNetworkQueue{
(object as InjectorDelegateNetworkQueue).networkManager = networkManager
}
}

Set delegate to class type not to instance in Swift

In Objective-C it was possible to set a class as a delegate (not an instance of a class but a pure class). Is it possible in Swift?
Yes it is
Declare a delegate variable to be a class type, not instance type.
I also make it optional, but we could also make it non-optional and pass it in the init method.
var delegate : Int.Type?
Code Example
class A {
static func sayHello() {
println("Hello")
}
}
class B {
var num = 10
var delegate : A.Type?
func hi() {
delegate?.sayHello()
}
}
var b = B()
b.delegate = A.self
b.hi()

How to declare a function with a concrete return type conforming to a protocol?

EDIT:
This question was written before swift added the some keyword, making it obsolete
In objective-c I could declare a method with a return type:
-(UIView<MyProtocol> *)someMethod;
In this example the method returns a UIView that conforms to a protocol MyProtocol.
I want to do something like that in swift:
protocol MyProtocol {
var someProperty : Int {get set}
}
protocol MyDelegate {
func someMethod() -> UIView : MyProtocol // the view should conform to the protocol - I don't care what kind of view it is - I don't want to define a specific type of view
}
In general - The delegate should return a UIView with the var "someProperty"
I don't want to define a concrete UIView class.
I want the user to be able to return any type of UIView (As long as it conforms to the protocol)
The syntax I wrote is invalid - How should I be writing it?
You could just use the protocol as type:
protocol MyDelegate {
func someMethod() -> MyProtocol
}
And use it like this:
protocol MyProtocol {
var someProperty : Int {get set}
}
class CustomView: UIView, MyProtocol {
var someProperty = 2
}
protocol MyDelegate {
func someMethod() -> MyProtocol
}
struct Delegate: MyDelegate {
func someMethod() -> MyProtocol {
return CustomView()
}
}
let delegate = Delegate()
let view = delegate.someMethod()
let property = view.someProperty // property = 2
This is not possible in Swift. Not everything possible in Obj-C has to be possible in Swift. When creating a type requirement you can only combine protocols using the protocol<..., ...> syntax but you can't combine a class and a protocol.
Technically, this should be good for your architecture. You can probably find a workaround but I would advice against it. There is a reason to avoid combining classes with protocols because the interfaces are much more difficult to handle. Most OOP languages don't have that syntax. Many commonly used languages don't even have a syntax to combine protocols.
protocol MyProtocol {
var someProperty : Int {get set}
}
protocol MyDelegate {
func someMethod<T: UIView & MyProtocol>() -> T // the view should conform to the protocol - I don't care what kind of view it is - I don't want to define a specific type of view
}
class MyDelegateTestView : UIView, MyProtocol {
var someProperty: Int = 10
}
class MyDelegateTestClass : MyDelegate {
func someMethod<T>() -> T where T : UIView, T : MyProtocol {
return MyDelegateTestView() as! T
}
}
The question was written before the days of swift-ui
The "some" keyword has solved it by allowing opaque types to be returned from functions
protocol MyDelegate {
func someMethod() -> some MyProtocol
}
Here below is a way.
func myMethod(string: String) -> MyClass:MyProtocol? {
}
You can use without optional type as MyClass: MyProtocol.

Compiler error when assigning the Delegate for a Protocol in Swift iOS

I have a problem assigning the delegate for an object that is an instance of a class that defines a protocol in Swift as follows:
I simplified the code to the bare bones to exemplify the issue:
This is the class with the protocol
protocol TheProtocol {
func notifyDelegate()
}
class ClassWithProtocol: NSObject {
var delegate: TheProtocol?
fire() {
delegate?.notifyDelegate()
}
}
This is the class the conforms to the Protocol
class ClassConformingToProtocol: NSObject, TheProtocol {
var object: ClassWithProtocol?
func notifyDelegate() {
println("OK")
}
init() {
object = ClassWithProtocol()
object?.delegate = self // Compiler error - Cannot assign to the result of this expression
object?.fire()
}
}
I have tried all sort of alternatives to assign the delegate without success. Any idea what I am missing?
The Known Issues section of the Release Notes says:
You cannot conditionally assign to a property of an optional object.
(16922562)
For example, this is not supported:
let window: NSWindow? = NSApplication.sharedApplication.mainWindow
window?.title = "Currently experiencing problems"
So you should do something like if let realObject = object { ... }

Resources