Showing posts with label iOS design patterns. Show all posts
Showing posts with label iOS design patterns. Show all posts

Friday, May 1, 2015

Defining a service layer with AFNetworking

This example shows how to create a service layer for json based web services. This is how I developed it.
  1. Create a basic interface for calling web services
  2. Create a subclass of correct AFNetworking seralizer class(in this case AFJsonSerializer) and format the response
  3. For each web service create a singleton subclass of AFHttpSessionManager
  4. Create a Façade for service layer
For this example I am using free web service used used by raywenderlich afnetworking tutorial

1 Creating basic interface
In modern software engineering, we write code for the interface, not for the implementation. So create a protocol named Service as folows
@protocol Service <NSObject>

- (void)callService:(NSDictionary*)parameters withCompletionBlock:(void(^)(NSArray *resultArray, NSError *error))completionBlock;

@end

This has a method called callService and it is the method used to call the web services. Now we have an interface, which can be used to call web services. I will explain the importance of this when we actually call a web service.

2 Creating a custom json response serializer
Here, we get the response in json format. we need to process this json response in order to get the correct result out of it. For that purpose we can create a subclass of the AFJSONResponseSerializer class and override it's responseObjectForResponse as follows. This method is overridden according to the json response we get. This method directly create models from the response and add it to an array
@implementation WeatherServieJasonSerializer

- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(NSData *)data
                          error:(NSError *__autoreleasing *)error {
    NSMutableArray *retArray = [[NSMutableArray alloc] init];
    NSDictionary *json = [super responseObjectForResponse:response data:data error:error];
    NSDictionary *dictionary = json[@"data"];
    WeatherInfo *infoRet = [[WeatherInfo alloc] init];
    NSArray *arrData = dictionary[@"weather"];
    
    infoRet.tempMaxC = @([((NSString*)((NSDictionary*)arrData[0])[@"tempMaxC"]) integerValue]);
    infoRet.tempMaxF = @([((NSString*)((NSDictionary*)arrData[0])[@"tempMaxF"]) integerValue]);
    infoRet.tempMinC = @([((NSString*)((NSDictionary*)arrData[0])[@"tempMinC"]) integerValue]);
    infoRet.tempMinF = @([((NSString*)((NSDictionary*)arrData[0])[@"tempMinF"]) integerValue]);
    
    [retArray addObject:infoRet];
    
    return retArray;
}
@end
 
3 Creating a singleton subclass of AFHttpSessioManager to invoke web services.
For each web service you have, you need to create a separate class like this. In addition this class conform to the Service protocol and implements its callService method. Following is the code for the class.
.h file
#import "AFHTTPSessionManager.h"
#import "Service.h"

@interface WetherWebService : AFHTTPSessionManager<Service>

+ (WetherWebService*)getSharedInstance;

@end

.m file
#import "WetherWebService.h"
#import "WeatherServieJasonSerializer.h"

static NSString * const baseURLString = @"http://www.raywenderlich.com/demos/weather_sample/";

@implementation WetherWebService

+ (WetherWebService*)getSharedInstance {
    static WetherWebService *sharedInstance = nil;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        sharedInstance = [[WetherWebService alloc] initWithBaseURL:[NSURL URLWithString:baseURLString]];
        sharedInstance.responseSerializer = [WeatherServieJasonSerializer serializer];
    });
    
    return sharedInstance;
}

- (void)callService:(NSDictionary*)parameters withCompletionBlock:(void(^)(NSArray *resultArray, NSError *error))completionBlock {
    [self GET:@"weather.php" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
        completionBlock(responseObject, nil);
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        completionBlock(nil, error);
    }];
}

@end
 
4 Creating the service layer façade.
This is an implementation of façade design pattern. This creates an abstraction layer between the web service layer and the rest of the application. This is the source of ServiceLayerFacade.h file
@interface ServiceLayerFacade : NSObject

+ (ServiceLayerFacade*)getSharedInstance;
- (id<Service>)getWeatherService;

@end
#import "ServiceLayerFacade.h"
#import "WetherWebService.h"

@implementation ServiceLayerFacade

+ (ServiceLayerFacade*)getSharedInstance {
    static ServiceLayerFacade *sharedInstance = nil;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        sharedInstance = [[ServiceLayerFacade alloc] init];
    });
    
    return sharedInstance;
}
- (id<service>)getWeatherService {
    return [WetherWebService getSharedInstance];
}
This is how these web services should be called.
NSDictionary *parameters = @{@"format": @"json"};
    ServiceLayerFacade *serviceLayer = [ServiceLayerFacade getSharedInstance];
    id<Service> weatherWebService = [serviceLayer getWeatherService];
    [weatherWebService callService:parameters withCompletionBlock:^(NSArray *resultArray, NSError *error) {
        if (resultArray[0] != nil) {
            id<Tablelayout> tableModel = resultArray[0];
            _tableArray = [tableModel getTableRepresentation];
            [_weatherTable reloadData];
        }
    }];
Here, since we are using interfaces and a facade, we can completely hide the implementation details of the web service layer. Web service caller only knows of the uniform interface method to call the web service. He does not know the classes used to call the web service, the way response is processed etc. What he gets is model classes that can be directly used in his code. Now I will explain the beauty of this approach. We use Service interface to access the web service. And we do not know how the web service is called behind the scene and how the response is processed. Because of this we can change everything related to web service calling and processing without affecting rest of the layers.

Presenting the data
This is our model class
#import 

@interface WeatherInfo : NSObject

@property NSNumber *tempMaxC;
@property NSNumber *tempMaxF;
@property NSNumber *tempMinC;
@property NSNumber *tempMinF;

@end
Now we have the data retrieved from the web service stored in our model classes. Now how to present it? You can add a method to the model class to get some sort of array and show it in a table. But this is an extremely bad idea. Because a model class should not know how the data is presented. So here our basic problem is adding behavior to the model object, without affecting behavior of other objects from the same class. What is the design pattern we can use to achieve this? The answer is decorator pattern
 
Implementation of decorator pattern
I normally use categories to implement decorator pattern in objective c. In addition I declare category methods in a protocol as well. This protocol acts as an interface
#import 

@protocol TableLayout <NSObject>

-(NSArray*)getTableRepresentation;

@end

This is the category of the model class.
.h file
#import "WeatherInfo.h"
#import "TableLayout.h"

@interface WeatherInfo (TableRepresentation)<TableLayout>

@end

This is the .m file
#import "WeatherInfo+TableRepresentation.h"

@implementation WeatherInfo (TableRepresentation)

-(NSArray*)getTableRepresentation {
    return [[NSArray alloc] initWithObjects:self.tempMaxC,self.tempMaxF,self.tempMinC,self.tempMinF, nil];
}

@end
Then in code via the TableLayout interface I am getting the table representation as follows.

id<Tablelayout> tableModel = resultArray[0];
            _tableArray = [tableModel getTableRepresentation];
            [_weatherTable reloadData];
This is how I implemented the service layer. The complete example of this tutorial is available in GitHub.

Alternative approaches
  • This stackoverflow question presents few ways of developing a service layer using AFNetworking and ReactiveCocoa
  • You can use RestKit to get Core data models directly after web service calls

For any query, feel free to contact me via my linkedin profile. Happy coding!!!!

Tuesday, November 4, 2014

Concurrency problems in singleton design pattern - An objcective c example

Singleton pattern is a very common pattern in iOS. It is one of the easiest to understand. But if you do not fully consider the concurrency, you will come across bugs which are extremely difficult to find. Have a look the following code which looks completely normal.
+ (instancetype)sharedInstance    
{
    static SomeClass *obj = nil;
    if (!obj) {
        obj = [[SomeClass alloc] init];
    }
    return obj;
}
Looks normal right? But really it is not the case.
Here the if condition branch is not thread safe. If this method is invoked with multiple threads, this may happen. Assume you have two threads(A and B). Now A enters the if block and a context switch occurs before
obj = [[SomeClass alloc] init];
is executed. Next thread B enters the if block and allocates an instance of the singleton and exit. Then thread A gets the chance. It also starts inside the if block and creates the instance. Now you have two instances. Clearly this is not what you need in singleton pattern.

Solution
+ (instancetype)sharedIinstance
{
    static SomeClass *obj = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        obj = [[SomeClass alloc] init];
    });
    return obj;
}

Here dispatch_once() executes the block only a one time in a thread safe manner. So different threads will not be able to access the critical section as I showed earlier.
This is not the only problem with singleton. Here only instantiation is thread safe. A Class may have mutable objects. In that case we need to consider about the thread safety status of those objects. Otherwise reader writer problems may occur.
Assume you have a NSMutableArray inside the singleton class and you have read and write operations in to that NSMutableArray object. you need to do two things in order to ensure thread safety. Here there is a possibility for a reader/writer problem scenario.
What is the reader/writer problem?
Assume you are going to make an online purchase and there is only one item left. As long as you are doing only read operations it is ok. But if you do any database write operations there may be problems. If someone completes a transaction while you are doing the transaction a problem will occur. It is called the reader/writer problem.
With apple GCD we have a very easy solution for that. GCD has an implementation of a reader/writer queue. GCD manages everything for us. A dispatch barrier creates a synchronization point inside a concurrent dispatch queue. GCD ensures that the submitted block is the only item executed on the specified queue for that particular time. All items submitted to the queue prior to the dispatch barrier must complete before the execution of the block. After the block is finished queue returns to the its specified implementation.
We have a NSMutableArray as follows.
@property (nonatomic, strong) NSMutableArray array;

And read and write operations as follows.
- (void)addObject:(NSObject *)obj
{
    if (obj) {   
     [_array addObject:obj]; 
    }
}

- (NSArray *)getObj
{
    NSArray *array = [NSArray arrayWithArray:_array]; 
    return array;
}

Add this to the header file
@property (nonatomic, strong) dispatch_queue_t concurrentQueue;

Then when you add to the NSMutableArray instance, the adding object operation should be added with a dispatch barrier.
- (void)addObject:(NSObject *)obj
{
    if (photo) { 
        dispatch_barrier_async(self.concurrentQueue, ^{  
            [_array addObject:obj]; 
        });
    }
}

Also when you read data from the mutable array also you should do it via a serially dispatched block as follows.
- (NSArray *)getObj
{
    __block NSArray *array; 
    dispatch_sync(self.concurrentQueue, ^{ 
        array = [NSArray arrayWithArray:_array]; 
    });
    return array;
}

Now your singleton is thread safe!! For any query, feel free to contact me via my linkedin profile. Happy coding!!!

Tuesday, August 5, 2014

Proxy design pattern using core data

Normally Core data models extend from NSManaged objects. So the model objects we use are tightly coupled with core data. What if we need to keep our models independent over core data? Such an approach will be more flexible since the model objects can be easily reused even when we do not want to use core data. We can use protocols to achieve this effect. We can create a protocol and our core data models categories will conform to that protcol. Here is an example This is a message Entity which can be used to represent a chat message
Message.h

#import 
#import 

@interface Message : NSManagedObject

@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) NSNumber * dirty;
@property (nonatomic, retain) NSString * entityID;
@property (nonatomic, retain) NSData * resource;
@property (nonatomic, retain) NSString * resourcePath;
@property (nonatomic, retain) NSString * text;
@property (nonatomic, retain) NSNumber * type;
@property (nonatomic, retain) NSNumber * didRecieve;

@end
Message.m
#import "Message.h"

@implementation Message

@dynamic date;
@dynamic dirty;
@dynamic entityID;
@dynamic resource;
@dynamic resourcePath;
@dynamic text;
@dynamic type;
@dynamic didRecieve;

@end
The protocol for generic messages
@protocol PMessage 

-(NSNumber *) type;
-(NSString *) text;
-(NSString *) fontName;
-(NSNumber *) fontSize;
-(NSString *) textColor;
-(UIImage *) textAsImage;
-(BOOL) isMine;
-(NSString *) color;
-(void) setColor:(NSString*)color;
-(NSDate *) date;
-(UIImage *) thumbnail;
-(NSString *) entityID;
-(BThread *) thread;
-(NSNumber*)didRecieve;

@end
this is the header file of the NSManagedObject category which confirms to the protocol
#import "Message.h"
#import "PEntity.h"
#import "PMessage.h"

@interface Message(Additions)

-(BOOL) sameDayAsMessage: (Message *) message;
-(NSComparisonResult) compare: (Message *) message;
-(BOOL) isMine;
-(float) getTextHeightWithFont: (UIFont *) font withWidth: (float) width;
-(UIImage *) textAsImage;
/**
Other presentation specific methods
****/

@end
The implementation of those methods resides within the .m file of the Message category. Through out the code I can refer to the message entity via PMessage protocol. The actual object whether it is a Message entity or some other message entity with some other non-core data storage mechanism, is determined at the run time. Assume you have developed a new storage mechanism that far exceeds the capabilities of core data. Now it is the time for use it. These are the steps you will have to preform
  • Create the model class based on the new storage mechanism.
  • Create a category of the model class based on the new storage mechanism that conforms to PMessage protocol

in the code I am always referring to the PMessage protocol. Because of that despite the actual object which encapsulates the actual data persistence mechanism all the object of PMessage type can be accesed with a uniform interface. For any query, feel free to contact me via my linkedin profile.