Attending UIKonf

Yesterday I was in Berlin (always worth to go there) for attending the UIKonf: an iOS developers conference. The location (Heimathafen) was awesome! Pretty good atmosphere, and awesome coffee all day. Yay!

The talk line-up was good as well. They had four rounds of sessions. All in one room, and each round had three sessions, that were scheduled to be 30 minutes: Perfect for getting quickly to the point!

The first session was pretty geeky. Joris Kluivers showed the Core Bluetooth Framework and did fancy things with a Mac, an iPhone and an actual lamp :) The second talk (by Boris Buegling) was about the Objective-C Runtime. He showed common things like introspecting objects/methods or associative references. While talking he mention some of the Github Frameworks, like Mantle or libextobjc as good examples. Daniel Eggert gave a pretty basic overview on CoreData. Being a formal Apple employee he gave some hints regarding performance and optimizations. IMO the most interesting statement was given at the end: Do NOT use NSIncrementalStore.

Afterwards I asked and he explained that using remote/http for CoreData just feels wrong. Indeed, I have been there with AFIncrementalStore too! Generally,… I am not that sure on CoreData…, and it looks like that most attendees were also not fans of CoreData :)

Robb gave a cool presentation about another Github Framework, called Reactive Cocoa, which is an Objective-C framework for Functional Reactive Programming: It provides APIs for composing and transforming streams of values. It’s a nice framework, but not 100% sure we really need to integrate it into the AeroGear-iOS library…

Since I am very interested in testing, I really did enjoy Tim Brueckmann‘s talk on “Testing and iOS”. The talk was common sense, IMO and frameworks like Kiwi (for BDD) or OCUnit got mentioned. One thing I took away was OHHTTPStubs. Currently we have our own “NSURLProtocol” impl, so that may go away :)

Another talk, by Florian Kugler, was on tooling/instruments. He showed how these tools can be used to find memory leaks and other issues with your code. A few talks were on Design and User Interaction. It’s not really my topic, but it was also not that bad :) The last talk given by Peter Steinberg was about tricks in your code, including some impressive reverse engineering.

The afterparty was at the Edelweiss bar/restaurant. With a few cold drinks the discussions continued all night long. Funny fact: a few mentioned their desire for something like generics, which I totally agree with!

For me it was a win, attending the conference. Various chats with folks that are longer doing iOS development was helpful, in kinda understanding that community. Also seeing we are using the right tools and libraries was good :) I think, it was also a bit interesting, that there were no talks on popular frameworks like AFNetworking or CocoaPods.

Thanks to Chris Eidhof et al. for running such a great conference. I will come back :)

Confess Vienna

Last week I was attending the Confess Conference in Vienna. It was a pretty good conference with interesting attendees and talks. Most talks were in the “Enterprise Java” range (Java EE and Spring); added with content around Big-Data, and JavaScript/HTML(5).

I gave a presentation about using HTML/JavaScript bits with a RESTful JavaEE backend (meaning JAX-RS). It was an overview on different frameworks/libraries out there, demonstrated on-top of the AeroGear TODO backend demo:

  • jQuery / jQuery Mobile
  • Backbone.js
  • AeroGear.js
  • Angular.js

The client demo applications where executed in three different “containers”:

  • desktop browser
  • mobile browser (iOS simulator)
  • Apache Cordova application (iOS simulator)

For the last demo, I showed our new AeroGear plugin for JBoss Forge (details here). It basically generates a JavaEE application, which uses Angular.js (for view templates and model declaration) and AeroGear.js (for the HTTP communication) as it’s Web technology.

Once the app is deployed it can be used in a (mobile) browser. The really cool part is that the HTML/JS bits from the generated app can be used as a native mobile app, by using Apache Cordova’s CLI with just a few steps! (A blog entry will follow…)

Going was worth it and seeing old friends is always fun. Thanks to Irian for having me at Confess! My slides are here: http://people.apache.org/~matzew/Confess_2013

AeroGear iOS 1.0.0

Today the AeroGear team is very happy to announce the 1.0.0 release of our iOS libraries:

The aerogear-ios project is a utility to communicate with remote server and storing data. The functionality of the library covers these areas:

  • HTTP REST abstraction + Paging
  • Authentication and User enrollment
  • Store and DataManager

TODO application was built that shows the library, by communicating with our TODO application, on OpenShift.

AeroGear meets Security

The aerogear-otp-ios project contains an iOS library for generating one time passwords according to RFC 6238. My colleague Christos Vasilakis describes the library here. Feel free to give the little demo a try as well!

More Documentation and Xcode Template

Besides the libraries there are more goodies! The project offers a neat template for Xcode, to kickstart your development.Check it out! We also increased the documentation with a little Cookbook

We hope you enjoy this release. We strongly encourage you to help us improving the project with feedback on the mailing list, or via our JIRA instance

AeroGear 1.0.0 – Candidate Release 1

Today we released our CR1!

So, what’s new in iOS?

With the new 1.0.0.CR1 release, we continued to focus on stabilisation! Besides adding more tests and maintainance, we have improved existing APIs and added a few new features.

The AGStore protocol is now allowing you to apply filterings, by using the NSPredicate class (see here).

The AGPipe protocol has a cancel (see here) to cancel running requests and its configuration is now aware of applying a timeout interval.

Besides that, the OTP demo has been polished to run against a JSON-based backend.

The library can be found on CocoaPods! Enjoy!

As always, feedback is more than welcome!

CoreData – Data Mapping with AFIncrementalStore

The AFIncrementalStore is a concrete implementation of the NSIncrementalStore API (see Chris’ blog and NSHipster for more details), which allows you to access remote endpoints, like RESTful “Web Services”, by using the CoreData API.

The project has three simple examples, including how to apply type mapping, in cases when you can’t use the JSON key in your class, like ID or description (as these are ObjC key words).

As shown in the examples, you need to override the attributesForRepresentation:ofEntity:fromResponse method, like:

- (NSDictionary *)attributesForRepresentation:(NSDictionary *)representation
                                     ofEntity:(NSEntityDescription *)entity
                                 fromResponse:(NSHTTPURLResponse *)response
{
    NSMutableDictionary *mutablePropertyValues =
       [[super attributesForRepresentation:representation
                                  ofEntity:entity
                              fromResponse:response] mutableCopy];

    if ([entity.name isEqualToString:@"Task"]) {
        NSString *description =
          [representation valueForKey:@"description"];
        [mutablePropertyValues setValue:description forKey:@"desc"];
    }
    return mutablePropertyValues;
}

The above code basically says that on the Task entity (managed object) the desc property is used to store the result of the description key in the JSON response. However, the above code only works for reading…

In case you want to create or update a new entity, you need to override the representationOfAttributes:ofManagedObject method like below:

- (NSDictionary *)representationOfAttributes:(NSDictionary *)attributes
                             ofManagedObject:(NSManagedObject *)managedObject {

    NSMutableDictionary *mutablePropertyValues =
        [[super representationOfAttributes:attributes
                           ofManagedObject:managedObject] mutableCopy];

    if ([managedObject.entity.name isEqualToString:@"Task"]) {
        NSString *description = [managedObject valueForKey:@"desc"];
        [mutablePropertyValues setValue:description forKey:@"description"];
        [mutablePropertyValues removeObjectForKey:@"desc"];
    }
    return mutablePropertyValues;
}

This code is basically the other way around… it reads the value from the managed object property (here desc), and stashes that on a dictionary, which is used by the underlying HTTP Client, to send the form data to the server. Inside of that dictionary, we are using the description key, that is required by our RESTful web service. To be safe… remove the odd desc field from the dictionary. Otherwise you may receive an error since the server does not like/understand the desc filed in the request….

Once you managed this little oddnes, it’s straightforward. As mentioned before, the ObjC type mapping to/from JSON is a little odd… This (of course) applies to CoreData and it’s managed objects as well.

 

AeroGear iOS lib – Milestone 2

Today we, the AeroGear team at Red Hat, released the second version of our little iOS library, containing these new features:

  • configuration objects
  • query and search parameters
  • OTP (One-Time Password)
  • Model APIs and CoreData

What’s new in iOS?

Below the features are described in a few sentences.

configuration objects

After the first milestone release, one key point was making the API a bit nicer. Instead of having lot’s of (long) methods to provide several configuration options, we decided to use a configuration object that’s passed in to a block:

id projects = [pipeline pipe:^(id config) {
   [config name:@"projects"];
   [config type:@"REST"];
}];

As shown above, when creating a pipe, a configuration object is passed into the block function, where the App developer can specify the desired values for his pipe. This is also a nicer way, compared to using the builder “pattern”, which is more common in the Java world as described here.

query and search parameters

Further, initial work has been done to support quering and paging of the data. Currently implemented in the Pipeline using the readWithFilter method, will allow you to specify your query (where clause) and paging (limit/offset) requirements, which will then be passed on your remote endpoints to process. Work is in progess, to support quering and paging on the local DataStore, exploiting some of the fine mechanisms that the iOS provides (e.g. NSPredicate) and of course provide easier abstractions for our users to work with.

Quering and Paging is going to play an important role in the next couple of releases. Currently, there is an ongoing discussion in the mailing list, so if there is correct time to get involved it is now! We would be more than happy to hear your ideas and suggestions.

Model APIs and CoreData

The current AGPipe API is using collections for persisting and receiving “objects” (e.g. NSDictionary is used to represent the object state in a key/value fashion):

...
NSMutableDictionary* projectEntity = .....

// save the 'new' project:
[projects save:projectEntity success:myCallback failure:errorCallback];

The generic aspect of this means that your are pretty flexible in writing your own Model API layer. You could even use Github’s new Mantle Framework, like described here. We do have a demo app, using Mantle in our repository.

CoreData outlook
We started looking to support CoreData, but that will not happen over the above pipe API. The idea is to use the AFIncrementalStore to support the mapping of CoreData to HTTP, so that you can easily access our backend. The current plan is to have a subclass of UIManagedDocument, which uses a AFIncrementalStore instance for the HTTP/CoreData mapping. The benefit would be that iOS/CoreData developers can continue to use known and established APIs (e.g. ManagedObjectContext, NSFetchRequest, FetchRequestController etc). They would just use a different UIManagedDocument (sub)class.

OTP

My co-worker Christos Vasilakis (author of the famous JBoss Admin iOS app) wrote a detailed blog post how the AeroGear project is now support OTP on different platforms. Check it out!

We want feedback!

As always, if there are concerns or missing features, let us know! Join the mailing list for discussion, hangout on our #aerogear IRC channel or even file bugs! We are happy to hear your thoughts and feedback!

Have fun!

Writing mock tests for AFNetworking

Mocking is not new and in the iOS space there is a nice library called OCMock. For HTTP communication the best library is AFNetworking. Both frameworks have some documentation on their project page, so I am not repeating basics here. For OCMock I also liked this article by Alex Vollmer.

Mock the HTTP access

Recently I had the requirement to mock the HTTP inside of “service classes”, that use the AFHTTPClient class for the network job. What I wanted to do is basically mock the (JSON) result of the HTTP GET request. With OCMock, it’s not that hard:

// create a mock of the AFHTTPClient:
id mockClient = [OCMockObject mockForClass:[AFHTTPClient class]];

// 1) build the expectations
//  * we expect that the "getPath" is invoked, once!
//  * here we don't care too much about the passed in arguments...
[[mockClient expect]
   getPath:[OCMArg isNotNil]
   parameters:[OCMArg isNil]
   success:[OCMArg isNotNil]
   failure:[OCMArg isNotNil]] ;

// 2) run the actual test:
    [mockClient getPath:@"projects"
       parameters:nil
       success:^(AFHTTPRequestOperation *operation, id responseObject) {
          NSLog(@"SUCCESS");
       }
       failure:^(AFHTTPRequestOperation *operation, NSError *error) {
           NSLog(@"FAIL");
    }];

Ok, that’s nice and the test passes – but none of the give blocks has been invoked.. In order to fake (->mock) a JSON response, we need to make sure that our ‘success’ block is invoked. That’s quite simple with OCMock. The library offers an andDo method, were we are able to get access to all the agruments of the later invocation of the “getPath” method from the AFHTTPClient class:

// create a mock of the AFHTTPClient:
id mockClient = [OCMockObject mockForClass:[AFHTTPClient class]];

// 1) build the expectations
//  * we expect that the "getPath" is invoked, once!
//  * here we don't care too much about the passed in arguments...
//  * we use the andDo function to invoke the GIVEN (notNil) success block with our mocked JSON
[[[mockClient expect] andDo:^(NSInvocation *invocation) {

    // we define the sucess block:
    void (^successBlock)(AFHTTPRequestOperation *operation, id responseObject) = nil;

    // Using NSInvocation, we get access to the concrete block function
    // that has been passed in by the actual test
    // the arguments for the actual method start with 2 (see NSInvocation doc)
    [invocation getArgument:&successBlock atIndex:4];

    // now we invoke the successBlock with some "JSON"...:
    successBlock(nil,
      [NSDictionary dictionaryWithObjectsAndKeys:@"Bom Dia", @"greetings", nil]
    );

}] getPath:[OCMArg any] parameters:nil success:[OCMArg any] failure:[OCMArg any]] ;

// 2) run the actual test
[mockClient getPath:@"projects" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
  STAssertEqualObjects(
     @"Bom Dia",
     [responseObject objectForKey:@"greetings"],
     @"Some faked JSON"
  );

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"FAIL");
}];

Now this test passes as well, and the responseObject contains the NSDictionary (-> JSON) that we created inside of our expectations… Of course only the success block was invoked, but invoking the failure block is not that much harder.

Using Mantle with AeroGear

The last two days I looked at Mantle, and how it solves some issues, when working with JSON and a rich domain model. Now, how to use the Mantle framework with AeroGear’s iOS library?

The Model – with Mantle

Ok, here is a quick snippet of a model:

@interface AGTask : MTLModel

@property(strong, nonatomic) NSNumber *recId;
@property(copy, nonatomic) NSString *title;
@property(copy, nonatomic) NSString *description;

@end

In the implementation we simply map the JSON id value to our recId field, since the ‘id’ is a reserved keyword in Objc:

@implementation AGTask

@synthesize recId;
@synthesize title;
@synthesize description;

+ (NSDictionary *)externalRepresentationKeyPathsByPropertyKey {
    return [super.externalRepresentationKeyPathsByPropertyKey
       mtl_dictionaryByAddingEntriesFromDictionary:@{
           @"recId": @"id"  // map the 'id' JSON string to our recId field!
     }];
}
@end

Using AeroGear

The AeroGear API is explained in here, but below is a quick snippet, how to create a AGPipe instance to send the object to the server:

// NSURL object:
NSURL* serverURL = [NSURL URLWithString:@"http://myserver.com/application/"];

// create the 'todo' pipeline, which points to the baseURL of the REST application
AGPipeline* todo = [AGPipeline pipeline:serverURL];

// Add a REST pipe for the 'projects' endpoint
id<AGPipe> tasks = [pipeline pipe:^(id<AGPipeConfig> config) {
    [config name:@"tasks"];
    [config type:@"REST"];
}];

Now that we have the tasks pipe, we can create a AGTask object and send it to the server, using Mantle’s externalRepresentation function:

// create a model object:
__block AGTask* task = [[AGTask alloc] init];
tasks.title = @"Create a screencast";
tasks.description = @"Show how the things work...";

// store the ObjC object on the server and replace it with the returned object
[tasks save:[task externalRepresentation] success:^(id responseObject) {
    // Replace the object with the response:
    task = [AGTask modelWithExternalRepresentation:responseObject];
} failure:^(NSError *error) {
    // when an error occurs... at least log it to the console..
    NSLog(@"SAVE: An error occured! \n%@", error);
}];

When the server has created the object, the returned (JSON) object contains a value for the “id” field, specified by the server. Inside of the success block, we update the task object with its latest representation, using another utility from Mantle, the modelWithExternalRepresentation class method.

Outlook

Right now the AeroGear library does not (yet?) internally use the Mantle framework, but the TODO demo app is using Mantle on a branch – for evaluation an inspiration!

Enjoy!

Objective-C: Working with JSON and mapping it a rich domain model

Transforming Objects to JSON and building up an object graph from a JSON response is pretty standard. But how is it done with Objective-C? Imagine a very simple class Task:

@interface Task : NSObject

@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;

@end

and let’s create an instance for the class:

Task* task1 = [[Task alloc] init];
task1.desc = @"some description...";
task1.title= @"My Title";

Cool! Now imagine you want the following JSON string:

{
   "title" : "My Title",
   "desc" : "some description..."
}

Ok that should be easy, especially since there is JSON support for iOS and also built-in to the iOS 5 SDK:

NSData* encodedData = [NSJSONSerialization dataWithJSONObject:task1 options:NSJSONWritingPrettyPrinted error:nil];
NSString* jsonString = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];

Ok, this does NOT work – the dataWithJSONObject call explodes, saying Invalid top-level type in JSON write

Trying a different JSON library does NOT fix it:

SBJsonWriter* writer = [[SBJsonWriter alloc] init];
NSString* str = [writer stringWithObject:task1];

There is no JSON string afterwards – the value is nil … That’s sad!

JSON: How does it work

Well, the above (JSON) libraries work on Foundation classes like NSDictionary. If you are able to return your object in a map form, these libs work just fine:

// a map that represents the above introduced task object...:
NSDictionary* task1 = [NSDictionary
   dictionaryWithObjectsAndKeys:@"some description...", @"desc", @"My title", @"title", nil];

NSData* encodedData = [NSJSONSerialization dataWithJSONObject:task1 options:NSJSONWritingPrettyPrinted error:nil];
NSString* jsonString [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];

Since we use the pretty write option the JSON looks like:

{
  "title" : "My title",
  "desc" : "some description..."
}

So yeah, we really need maps that are representing the object graph… Nice…

Manual maps

Having the requirement to manually implement a get object as dictionary and one create from dictionary function is a bit odd. However it is a pattern, which is used sometimes…  Something more magic/automatic would be nice, other have figured out that too…

There is a framework called JAGPropertyConverter that helps to transform object graphs into a NSDictionary that can be used with various JSON libraries. Now let’s make the object graph a little bit more complex… We add an Employee that can have n tasks…

@interface Employee : NSObject

@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSArray* tasks;
@end

...
...
Employee* employee = [[Employee alloc] init];
employee.name = @"Mr. X";
employee.tasks = [NSArray arrayWithObjects:task1, task2, nil];

Now using the JAGPropertyConverter, we can easily transform the graph:

...
JAGPropertyConverter *converter = [[JAGPropertyConverter alloc] initWithOutputType:kJAGJSONOutput];
converter.classesToConvert = [NSSet setWithObjects:[Task class], [Employee class], nil];
NSDictionary *jsonDictionary = [converter convertToDictionary:employee];

...
SBJsonWriter* writer = [[SBJsonWriter alloc] init];
NSString* str = [writer stringWithObject:jsonDictionary];

The little downside is that I have to provide some information about my custom types (see classesToConvert)…

Parsing JSON

Writing out JSON is one thing – parsing the other. To make a long story short – similar issues are present when trying to transform a JSON string to a rich object model… The JSON parser libraries expect an array (NSArray) or a map (NSDictionary). So we need something that is able to transform the NSDictionary into a rich object graph…

For that I have tested the KeyValueObjectMapping framework and also used the already discussed JAGPropertyConverter. Both function similar: With a little information about the used custom types, they are able to create an object graph out of the JSON data structures (NSArray, NSDictionary).

Github’s Mantle

An other interesting option could be Github’s Mantle. As stated on their project side, Mantle makes it easy to write a simple model layer for your Cocoa or Cocoa Touch application. It also adresses the JSON issue, as it offers an automatic/magic externalRepresentation function that returns a NSDictionary of the object (its state). However, your classes now needs to inherit from the MTLModel class:

@interface MantleTask : MTLModel

@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;

@end

Getting the map/NSDictonary of one class is simple and generating the JSON is easy too:

MantleTask* task = [[MantleTask alloc] init];
task.title = @"Some task";
task.desc = @"lot's of workz";

NSData* encodedData = [NSJSONSerialization
    dataWithJSONObject:[task externalRepresentation]
    options:NSJSONWritingPrettyPrinted error:nil];

NSString* jsonString = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];

The pretty JSON output looks like:

{
  "title" : "Some task",
  "desc" : "lot's of workz"
}

The Mantle framework also supports nested classes, but you have to also include some type-mapping information as well:

@implementation MantleEmployee
+ (NSValueTransformer *)tasksTransformer {
    return [NSValueTransformer
       mtl_externalRepresentationArrayTransformerWithModelClass:MantleTask.class];
}
@end

This class function knows about it’s subtypes… So again some information on the actual type system is needed.

Summary

Generally the Mantle Framework provides a (somewhat) clean solution for:

  • generating maps (->JSON) out of an object graph
  • generating object graphs from maps (->JSON)

Of course, Mantle also supports the case where the external representation (e.g. JSON) changes – you simple implement some mapping function, as shown on their project side.

So far Mantle looks like a great library when transforming objects to an external representation. I also appreciate the dynamic/magic support for creating an object from a map:

NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* parsedObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

MantleEmployee* parsedEmp = [[MantleEmployee alloc] initWithExternalRepresentation:parsedObject];

Similar to the above shown “externalRepresentation” function, which creates a NSDictionary of my object graph!

AeroGear developer release

Yesterday we released a new version of the AeroGear library! Highlights are a more fluent API to create pipes,stores and authModules. Another milestone was the usage of using the previously discussed configuration objects!

Get it from the CocoaPods repo!

New way to create a AGPipe:

// NSURL object:
NSURL* serverURL = [NSURL URLWithString:@"http://todo-aerogear.rhcloud.com/todo-server/"];

// create the 'todo' pipeline, which points to the baseURL of the REST application
AGPipeline* todo = [AGPipeline pipeline:serverURL];

// Add a REST pipe for the 'projects' endpoint
id<AGPipe> projects = [pipeline pipe:^(id<AGPipeConfig> config) {
    [config name:@"projects"];
    [config type:@"REST"];
}];

New way to create a AGStore:

// create the datamanager
AGDataManager* dm = [AGDataManager manager];
// add a new (default) store object:
id<AGStore> myStore = [dm store:^(id<AGStoreConfig> config) {
    [config name:@"tasks"];
    [config TYPE:@"MEMORY"];
}];

New way to create a AGAuthenticationModule:

// create an authenticator object
AGAuthenticator* authenticator = [AGAuthenticator authenticator];

// add a new auth module and the required 'base url':
NSURL* baseURL = [NSURL URLWithString:@"https://todoauth-aerogear.rhcloud.com/todo-server/"];
id<AGAuthenticationModule> myMod = [authenticator auth:^(id<AGAuthConfig> config) {
    [config name:@"authMod"];
    [config baseURL:baseURL];
}];

As always, feedback and JIRAs are welcome!