I am making an app for iOS in Swift and I am trying to keep my API call logic outside of my ViewControllers. I followed this tutorial for 1 API call that I'll describe below.
I am creating a protocol 'APIControllerProtocol' that the ViewController will implement, and then I am creating an APIController class that will contain a property called 'delegate' to hold an instance of type APIControllerProtocol. The protocol is simply defined as
protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
}
And the ViewController will implement the didReceiveAPIResults function to be called after the API call returns JSON data. The ViewController will contain an instance of the APIController as well to call a function which makes the call to the API.
At this point I want to have more ViewControllers perform API calls, and if I only need to make 1 API call per ViewController, I can just add another function to APIController, and I can have the new ViewController use the same protocol. However, this logic is flawed if there is a ViewController that would need to make 2 or more API calls, because
I cannot call didReceiveAPIResults in the ViewController in 2 different ways,
I don't think adding multiple 'delegate' properties to the APIController class to hold different types of protocols is the way to go.
Defining multiple functions in a protocol would mean I would have to implement all of these functions in ViewControllers that only need to make 1 API call.
My ideas to solve this problem are
Make an APIController class and APIControllerProtocol for each ViewController
Use optional functions in the APIControllerProtocol so not every ViewController would have to implement all of the functions (I don't know how this would really work)
Any other insights would be appreciated.
Your use of the term "API" is confusing. It sounds like what you mean is a server request, so that's what I'm going to call it.
I would suggest using a completion block/closure design rather than a protocol-based design.
Make your calls to your network request class take a completion closure, and call that completion closure once the server request is done.
You can write your network request class to maintain a list of requests and the completion closure for each pending request, and invoke the closure for each request once it completes or fails.
Defining multiple functions in a protocol would mean I would have to
implement all of these functions in ViewControllers that only need to
make 1 API call.
This is incorrect. Create optional functions and you probably have your answer.
#objc protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
optional func someAwesomeMethod()
}
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
Optional Protocol Requirements
You can define optional requirements for protocols, These requirements
do not have to be implemented by types that conform to the protocol.
Optional requirements are prefixed by the optional modifier as part of
the protocol’s definition.
An optional protocol requirement can be called with optional chaining,
to account for the possibility that the requirement was not
implemented by a type that conforms to the protocol. For information
on optional chaining, see Optional Chaining.
You check for an implementation of an optional requirement by writing
a question mark after the name of the requirement when it is called,
such as someOptionalMethod?(someArgument). Optional property
requirements, and optional method requirements that return a value,
will always return an optional value of the appropriate type when they
are accessed or called, to reflect the fact that the optional
requirement may not have been implemented.
The tutorial you're basing your logic on does not look ok to me. What it does, it implements a standard delegation pattern tweaked to the max. DetailsViewController has an APIViewController instance to which it assigns itself as the delegate - pretty standard. But then DetailsViewController calls methods on that APIViewController instance in order to get the delegate methods fired, which are implemented in DetailsViewController. That's too much going in circles for my taste.
A much more sensible pattern would be to create a singleton (shared instance) object which would handle your API calls and any view controller could access it. There you can implement your methods that take your parameters, one of them being a closure which could be called when your request completes passing the result to the view controller.
So in your view controller you'd call something like this:
APIController.sharedInstance.doSomethingWith(someParameter, completion: { (result) -> Void in
// Do something with the result
})
Your APIController would implement this something like this
func doSomethingWith(param: String, completion: (AnyObject) -> Void) {
// do your data fetching here...
// pass the result to the closure when the data is retrieved
completion(result)
}
Related
I am working on implementing an iOS version of an existing Kotlin Android app. The specific feature that I am reproducing is a stepped wizard workflow.
How I Did it in Android
In Android, the library that I used had the following process:
Add a "stepper" view to a root activity, and provide a StepAdapter to this view
The StepAdapter controls the number of steps, and returns each step on request by index.
Each step is a Fragment implementing a Step interface that provides hooks for validation and transitioning between steps.
I ended up creating an abstract Fragment type that provides default implementations for the Step methods:
abstract class StepFragment(private val index: Int) : Fragment(), Step {
...overriding some methods from Fragment
...implementing methods from Step
}
Each step's Fragment inherits this class, passing a hard coded index into StepFragment's constructor. The steps may override some of the methods from StepFragment, and some of them call the superclass's implementation as well (I use the #CallSuper annotation to facilitate this). The StepAdapter instantiates and returns each one of these fragments.
How I'm Trying to Do it in iOS
Back in the iOS/Swift world, I found a similar library, but all it provides is the view for the progress bar. It does not handle instantiating and displaying the content of each step like the Android one does. I need to handle that myself.
You can, however, provide a delegate to the stepper that allows you to hook into the transitions (willSelectIndex, didSelectIndex, canSelectIndex, etc.). I made the root ViewController the delegate for the stepper. This ViewController has the progress bar view at the top, and a container for each step beneath the progress bar. Each step's ViewController is embedded into a corresponding container. To control transitions between steps, I simply show and hide these container views. I have that part figured out.
What I do not have figured out is how to replicate the StepFragment class from Android Fragments into Swift ViewControllers. I have the following problems:
Swift does not have abstract classes (for some reason).
I do not instantiate the step ViewControllers; that is handled internally by the storyboard. This means that I can't provide the step index in the constructor like I can in Android. An abstract property would be the typical way to get around this, but (see above) Swift doesn't have abstract classes.
I could get around these problems in a few ways:
Instead of an abstract class, I can use a protocol. I can specify the requirement that all classes that conform to the protocol must be ViewControllers, but I cannot override methods from ViewController in the protocol (as far as I've been able to see). I can add an extension to the protocol to provide functions with default implementations, which implementors can then override, and they can even call into the original functions (using (self as Protocol).func()). However, this feels very clunky.
Instead of an abstract class, I can use a regular class. I can achieve everything that I want to here, except that I can't enforce that the subclass implements abstract members at compile time. I would need to use something like fatalError() in the base class, which only throws at runtime. This also feels clunky.
I keep hearing about the "delegate" pattern, and I think it's a nice elegant way to solve a lot of problems in a "Swifty" way, but I have no idea how I would use that here. I think I would prefer being able to do it this way over the above two.
TL;DR
To sum up my problem, I am looking for a way for multiple "step" child ViewControllers to hook into a wizard workflow controlled by a parent ViewController. They should be able to perform some (potentially async) logic on step selection, before transitions, and even block transitions. I must be able to optionally ignore some of these hooks, which should then use a default implementation.
I discovered that you actually can provide default implementations for protocol functions, so this is the solution I came to:
protocol StepViewController: UIViewController {
var stepIndex: Int { get }
func onBackClicked(_ goToPreviousStep: () -> Void)
...
}
extension StepViewController {
// this is a default implementation, so implementors don't have to provide it
func onBackClicked(_ goToPreviousStep: () -> Void) {
goToPreviousStep()
}
...
}
class StepOneViewController: UIViewController, StepViewController {
let stepIndex: Int = 0
func onBackClicked(_ goToPreviousStep: () -> Void) {
// if I want to call the default implementation I can do this:
(self as StepViewController).onBackClicked(goToPreviousStep)
}
}
The question (reflection or something like it?)
Is it possible (in Swift) to extract all the method signatures of an iOS protocol programmatically, such as for UITextViewDelegate, whose methods are all optional, without having to instantiate a separate class that explicitly implements all the protocol's methods?
In this case, want to intervene as the delegate to intercept one of the methods and do some related operation to that activity, then daisy chain the delegate call forward. But unfortunately, becoming the delegate entails responsibility to forward all of the protocol the downstream consumer
If you're saying what I think you're saying, there actually is a very simple way to do this: implement forwardingTarget(for:), as I do here:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch12p611tabBarMore/ch25p882tabBarMore/MyDataSource.swift
The idea is that I don't know what the table view's dataSource actually does, because the table view and its data source belong to Cocoa, but I want to act as a "man in the middle" between them and just tweak the behavior of one data source method if it is called. All other method calls just get passed along, without my even knowing what they are.
I have a login view controller. Once the login is done, it dismisses itself and calls a function in another view controller. And in that function there are four different functions that do different actions. The problem is the protocol calls 4 functions at the same time. So is there a way to call a specific function inside the other function? like;
func mainfunction(){
funcOne()
funcThree()
funcTwo()
funcOne()
}
So instead of calling all, I want to call one. And mainFunction is a part of protocol.
Thanks
Just extend your protocol. Instead of having one mainFunction, the protocol would have all four.
#protocol YourProtocol {
func funcOne()
func funcTwo()
func funcThree()
func funcFour()
}
If you add the separate functions in the protocol declaration, you will be able to call them individually if they exist.
The protocol serves as a contract of what should be implemented. It gives the compiler and developers a way of knowing what is supposed to be available. It's very similar to the concept of declaring functions ahead of time in a C header file. The functions are not available until you or someone else implements them.
I was just understanding the method swizzling done in obj c Method Swizzling and dangers of using method swizzling and couldn't help but draw a comparison between doing method swizzling and overwriting method implementation using categories.
They both help override the functionality of the predefined framework methods.
So is there any difference between the two or they can be used interchangeably?
The main difference is that Objective C prevents you from invoking the original implementation from a category override. This is because Objective-C's super invocations start from the super-class, while categories override methods on the same class level.
Method swizzling, on the other hand, lets you keep a reference to the original implementation as well, so that you could call it from inside your implementation. For example, in the article at your first link the author writes this:
- (void) logged_viewDidAppear:(BOOL)animated {
[self logged_viewDidAppear:animated];
NSLog(#"logged view did appear for %#", [self class]);
}
The second line makes a call to logged_viewDidAppear: method, which looks like an unconditional call to itself that should cause infinite recursion. However, this is not what happens: after swizzling, this call gets transformed into a call to the original viewDidAppear: because of the way method swizzling works.
In contrast, overriding a method from a category does not give you access to the logic of the method that you are overriding. It lets you replace the logic, but it does not let you extend it.
extension UIViewController{
public func myViewDidLoad(){
self.viewDidLoad()
//but you need to call this method everywhere replacing
}
//you cant do this
public func viewDidLoad(){
self.viewDidLoad()
//my code
}
}
Categories or extension let you do these:
Add computed properties and computed type properties
Define instance methods and type methods
Provide new initializers
Define subscripts
Define and use new nested types
Make an existing type conform to a protocol
(from Apple)
They don't let you extend original method of the same class that you are extending and if you try like the above code method signature conflict pops up.
You might want to check this website to get the concept diagrammatically. I really loved it.
http://matteogobbi.github.io/blog/2014/12/15/extending-methods-in-a-category-by-method-swizzling/
Make sure to check this awesome article for good implementation detail:
http://nshipster.com/method-swizzling/
I understand what a delegate does in iOS, and I've looked at sample code, but I'm just wondering about the advantages of this type of encapsulation (as opposed to including delegate methods in the primary object).
The advantage of the delegate design pattern is loose coupling. It enables class A (the delegate) to depend on class B (the delegating class) without class B having to have any knowledge of class A. This ensures that the dependency relationship is one-way only, rather than being circular.
It also forms the foundation (lower case "f") of Apple's frameworks because it allows them to invoke your code as appropriate when functionality specific to your application is required. For example, responding to a button tap or telling a table view how many sections there should be.
Delegation is a design pattern not only used in iOS but many other languages. It enables you to hand values and messages over in your class hierarchy.
In iOS, delegation requires the "delegate" class to implement a protocol which contain methods that the "delegating" knows about. Still following?
The delegating class's implementation will call these protocol methods, but the delegate class will implement these methods in their class.
This keeps your Classes clean.
In reality, you don't really need delegation if you can add new methods to a single class. But for UIKIT's UIView class, Apple will not allow you to add new implementations to their class.
correct me if I'm wrong.
The most common use of a delegate in iOS is to establish communication within modules that are unrelated or partially related to each other. For example, passing data forward in a UINavigationController is very easy, we can just use segue. However, sending data backwards is little tricky. In this case, we can use delegate to send the data backward.
Let's call, the class, associated with the first Controller ClassA and the class, associated with the second Controller ClassB. The first Controller is connected to the second controller with a forward segue. We can pass data from ClassA to ClassB through this segue. Now, we need to pass some data to ClassA from ClassB for which we can use delegates.
The sender class(ClassB) needs to have a protocol in its header file(.h) and also a reference of it as delegate inside the block, #interface ClassB .... #end. This reference let's the ClassB know that it has a delegate. Any class that wants to use this ClassB will have to implement all of this protocol's required methods(if any). So, the receiver class,ClassA will implement the method but the call will be made by the sender class, ClassB.
This way, receiver class doesn't need to worry about the sender class' internal structure, and can receive the required information.
Delegation as I understand it is when an object will pass the responsibility of handeling an event to another object thus "delegating" the responsibility to that object.
For example if you have an NSButton in iOs you generally assign the Delegate to be the parent view controller. This means instead of handeling touchUp events in the definition of the button it is instead handled in the view controller.
The main advantage of delegation over simply implementing methods in the "primary object" (by which I assume you mean the object doing the delegating) is that delegation takes advantage of dynamic binding. At compile time, the class of the delegate object does not need to be known. For example, you might have a class that delegates the windowDidMove: method. In this class, you'd probably see some bit of code like
if([[self delegate] respondsToSelector:#selector(windowDidMove:)]) {
[[self delegate] windowDidMove:notification];
}
Here, the delegating class is checking at runtime whether its delegate responds to the given method selector. This illustrates a powerful concept: the delegating class doesn't need to know anything about the delegate other than whether it responds to certain methods. This is a powerful form of encapsulation, and it is arguably more flexible than the superclass-subclass relationship, since the delegator and the delegate are so loosely coupled. It is also preferable to simply implementing methods in the "primary object" (delegating object), since it allows runtime alteration of the method's implementation. It's also arguable that this dynamic runtime makes code inherently more dangerous.
Delegate is an important design pattern for iOS app.All apps directly or behind the hood use this delegate pattern.
Delegate design pattern allows an object to act on behalf of another.
If we are working with tableview then there are "tableViewDelegate" and "tableViewDataSource". But what this means
Suppose you have a tableview.
now some major concern for this.
1.what is the datasource(the data that will appear in table view) for this tableview?
2.How many row for table view etc.
delegate design pattern solve these question using another object as the provider or the solver of these question.
An object mark himself to the table view and ensure the table view that "Yes i am the man who can assist you" by marking himself as the delegate to the table view .Thanks
The class marked as delegate takes the responsibilities to handle the callbacks sent while some event occurs. For example, in case of UITextField, there are some methods called when some events occurs like editing started, editing ended, character typed etc. These methods will already be defined in the protocol. We will have to assign delegate for that i.e. which class is going to handle these events.
With the help of a delegate, two-way communication can be achieved. A delegate might be used to make an object reusable, to provide a flexible way to send messages, or to implement customization.
In iOS ecosystem especially UIKit Framework which consists of UIApplication, UITableView, UICollectionView, UITextfield & so on uses delegate & datasource design pattern intensively to communicate data to and fro.
Delegate design pattern is used to pass/communicate data from FirstVC(Delegator) to SecondVC(Delegate) to complete a task.
Here, SecondVC(Delegate) conforms to a protocol delegate & implements all its requirements like methods by providing body to complete that task given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having a optional property of protocol delegate type i.e delegate which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method residing in SecondVC(Delegate) by passing data from its delegate property.
EX: CEO(FirstVC) which passes data i.e "confidential data" to Secretary(SecondVC) to do further processes using that data.
Datasource design pattern is part of Delegate pattern which is used to pass/communicate data from SecondVC(Delegate) to FirstVC(Delegator) when a task is assigned to SecondVC(Delegate).
Here, SecondVC(Delegate) conforms to a protocol datasource & implements all its requirements like methods with return type by providing body to talk back to FirstVC(Delegator) after the task is given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having an optional property of protocol dataSource type i.e dataSource which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method with a return type residing in SecondVC(Delegate) by passing data from its dataSource property.
EX: Secretary(SecondVC) replies back with a data i.e "Sir, I am already having too much work to do. Please, can you assign that data to others" to CEO(FirstVC). Now, CEO(FirstVC) will analyse that data to do further processes.
Delegation means one object passes behaviour to another object..