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.