Swift cast AnyObject to protocol and assign property - ios

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
}
}

Related

passing data to already implemented delegate methods inside extensions inside swift

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()

Delegate a structure in swift?

I am developing an app to increase a little more my knowledge about swift. One of my questions if is it possible to delegate a optional function with a structure as an argument.
What yes Im able to do:
#objc protocol someProtocol {
optional func optionalFunc(someClass: someClass)
}
class someClass: NSObject {
}
But, what I want to do (problems representing a structure in objc):
#objc protocol someProtocol {
optional func optionalFunc(someStructure: someStructure)
}
struct someStructure {
}
And Im not able to find the way to solve this problem.
And the other thing I want, is similar to this but with enums instead of structs:
#objc protocol someProtocol {
optional func optionalFunc(someEnum: someEnum)
}
enum someEnum {
case example
}
If somebody can help me, I will be very grateful!
Lot of thanks! Luciano!
Swift 2.0 lets you do default implementations of protocols.
protocol someProtocol {
func optionalFunc(someStructure: SomeStructure)
}
extension someProtocol {
func optionalFunc(someStructure: SomeStructure){
// optional, leave empty
}
}
struct SomeStructure {
}
This way you can get around using the optional-decoration and do what you wanted.
You cannot pass the parameters as struct or enum, because it's only valid on Swift language, so it cannot be represented in Objective-C.
Another approach, you can declare a function as variable instead of func:
protocol someProtocol {
var optionalFunc: (someStructure) -> ()? { get set}
}
Implementation:
class someClass : someProtocol {
var optionalFunc: (someStructure) -> ()? = { yourStruct in
// Do anything with yourStruct
return
}
}
Using:
var someVar:someClass = someClass()
var result = someVar.optionalFunc(someStructure())
The result is a ()?. If you do not implement the variable, result will nil

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()

Implement delegate using generic protocol in Swift

I'm trying to create a delegate protocol that implements a function which passes an array of a generic type. I've tried several combinations but none of them seem to do the trick.
This is the most approximate thing i've reached to. This is the protocol:
protocol APIControllerProtocol {
typealias T
func didReceiveAPIResults(results: [T])
}
And this is the the delegator object:
class APIController<U:APIControllerProtocol> {
typealias ElementType = U
var delegate: ElementType?
init(delegate: ElementType){
self.delegate = delegate
}
func getAPIResults(){
// Perform some action before delegation
// "results" is an Array of dictionaries got from NSJSONSerialization
self.delegate?.didReceiveAPIResults(results.map{dict in Album(json:dict)})
}
}
However, the last line get this error: "Album is not convertible to U.T"
"Album" is the model object used to return the results.
What am i doing wrong?
EDIT:
Following Mike S advice, i've made the protocol method didReceiveAPIResults a generic function, and specified what T is in the delegate. However, when receiving and assigning the argument of type T to a property in the delegate, i get the error: "T is not identical to T"
class TestDelegate: APIControllerProtocol {
typealias T = Album
var albums:[T] = [T]()
func didReceiveAPIResults<T>(results: [T]) {
// ...
self.albums = results //ERROR: "T is not identical to T"
}
}
Your didReceiveAPIResults declaration in APIControllerProtocol needs to be a generic function so that the generic type T is passed along to it correctly.
protocol APIControllerProtocol {
typealias T
func didReceiveAPIResults<T>(results: [T])
}
Note: This means your delegate definition will need to define what T is:
class TestDelegate: APIControllerProtocol {
typealias T = Album
func didReceiveAPIResults<T>(results: [T]) {
// ...
}
}
Update: While the code above does get rid of the original error, it turns out that it acts more like a workaround and doesn't really address the root of the problem.
The real issue seems to be that the compiler is having trouble reconciling what U.T is with no ambiguity. That's actually easy enough to fix though, we just need to give it a more precise definition (note the where clause in the APIController definition):
protocol APIControllerProtocol {
typealias T
func didReceiveAPIResults(results: [T])
}
class APIController<U:APIControllerProtocol where U.T == Album> {
typealias ElementType = U
// ...
}
Note: I removed the <T> that I added to the function in the protocol previously; that's not needed anymore and will end up causing problems later.
With that, the TestDelegate class works as expected (you don't even need the typealias anymore):
class TestDelegate: APIControllerProtocol {
var albums: [Album]? = nil
func didReceiveAPIResults(results: [Album]) {
albums = results
}
}

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