Write C as oriented programming language
Let's write some C as an oriented programming language
Hi astronauts, today we will keep talking about mobile development, and as always native style.
This article is following the 2 previous ones, and it's mandatory that you read them before, in order to understand what's going on in this one:
If you have already read the 2 previous articles, I guess you already have an idea about what this one is about.
How are we going to proceed?
As in the first article, so that everyone is happy, I will provide some DUMMY code for both Objective-C and Swift.
As you may know in the iOS universe, we can use both Delegates and Closures. Usually closure is used for more flexibility and it is also easier to implement. However, in some cases, graphic components for example are just made to work with a delegate or a datasource. Right now I'm thinking about 2 components: UITableView and UICollectionView.
With those 2 components, you cannot use block/closure, and you have to use a good old delegate. Usually it's not really a big issue and you can just work like that. But let's say that you have to work with many of those components on a single screen, in this case the code can start to be really messy. You'll find yourself with some huge classes, and it really starts to be difficult to produce some beautiful and elegant code. What I would like to show you today is a solution, that in my opinion is pretty clean and easy to set up.
As in the two previous articles, we will proceed with a GET call on a URL and build a system that will notify us in case of both success and error. We will go a little bit faster than in the first article, because those are notions that you are already suppose to master.
It's time to talk about code!
Our goal is to realize a class that performs a GET call on a URL. I want to notify the object that launched this request if it failed or succeeded. To avoid strong dependencies, we will use the delegate pattern, thanks to this I don't need to know the exact type of the object.
Let's do this in 3 steps:
typedef void (^successBlock)();
typedef void (^failureBlock)();
@protocol RequestManagerObjCDelegate
- (void)onRequestSuccess;
- (void)onRequestFailure;
@end
@interface RequestManagerObjCDelegateImplementation : NSObject
{
}
@property (weak, nonatomic) successBlock success;
@property (weak, nonatomic) failureBlock failure;
@end
@interface RequestManagerObjC : NSObject
- (void)get:(NSString*)url;
@property (nonatomic, weak) id delegate;
@end
We will now implement the class that will inherit from the protocol. It will contain the 2 methods onRequestSuccess and onRequestFailure and each of them will call the dedicated block/closure.
@implementation RequestManagerObjCDelegateImplementation
- (void)onRequestSuccess {
self.success();
}
- (void)onRequestFailure {
self.failure();
}
@end
Then, we code the class RequestManager that you are familiar with.
@implementation RequestManagerObjC
- (void)get:(NSString *)url {
//Do the call
BOOL requestSucceed = [self isSuccess];
//After the call
if (requestSucceed) {
[self.delegate onRequestSuccess];
} else {
[self.delegate onRequestFailure];
}
}
- (BOOL)isSuccess {
return YES;
}
@end
Then, we code the method to call our webservice.
- (void)callWebService { RequestManagerObjC* manager = [[RequestManagerObjC alloc] init]; successBlock success = ^void() { }; failureBlock failure = ^void() { }; RequestManagerObjCDelegateImplementation* delegate = [[RequestManagerObjCDelegateImplementation alloc] init]; delegate.success = success; delegate.failure = failure; manager.delegate = delegate; [manager get: @"http://plop.fr"]; }
Let's take a look on what we just coded.
Here is the Swift code for the most excited ones
protocol RequesterDelegateSwift {
func onRequestSuccess()
func onRequestFailure()
}
class RequesterDelegateSwiftImplementation: RequesterDelegateSwift {
var requestSuccess: ((Void) -> Void)?
var requestFailure: ((Void) -> Void)?
func onRequestSuccess() {
if let successClosure = self.requestSuccess {
successClosure()
}
}
func onRequestFailure() {
if let failureClosure = self.requestFailure {
failureClosure()
}
}
}
class RequestManagerSwift {
var delegate: RequesterDelegateSwift?
func get(url: String) {
//Do the call
let requestSucceed: Bool = self.isSuccess()
//After the call
if requestSucceed {
self.delegate?.onRequestSuccess()
} else {
self.delegate?.onRequestFailure()
}
}
private func isSuccess() -> Bool {
return true
}
}
func callWebService() {
let manager: RequestManagerSwift = RequestManagerSwift()
let requesterDelegate: RequesterDelegateSwiftImplementation = RequesterDelegateSwiftImplementation()
requesterDelegate.requestSuccess = {
}
requesterDelegate.requestFailure = {
}
manager.delegate = requesterDelegate
manager.get(url: "http://plop.fr")
}
Now, if I call the method callWebService, considering the dummy code we produced, the result will be a call to the block/closure requestSuccess.
But why do we bother to do all this?
Indeed, why do all this, especially in our case? We could just have used a Delegate or Blocks/Closures as we did in the first article. This adds a lot of complexity in the code, and it looks like we are doing the same things twice... As I told you at the beginning of the article, this solution comes for a specific case. To make a Delegate more flexible when you have no other choice that to use this pattern.
Issues
Benefits
This solution is not perfect, but still quite elegant and is not too heavy to implement. Then, I'll let you test it and give me some feedback in the comments section.
See you space cowboys :)
Author(s)
Thibaud Huchon
Plop
You wanna know more about something in particular?
Let's plan a meeting!
Our experts answer all your questions.
Contact usDiscover other content about the same topic
Let's write some C as an oriented programming language
Let's use the Framework in a way that it's not supposed to be