Skip to content

iOS SDK

Data objects

Vasat utlises the CoreData library for its ORM. A xcdatamodel file and support objective-c files are needed for every data type. Vasat data objects need to extend the class VasatBaseModel. This base mirrors the BaseModel class on the server side.

Working with Models

VasatBaseModel extends NSManagedObject. All local query operations available to NSManagedObject's are available. A local model can be created using the static class method make

MyObj* o = [MyObj make];
  
// this is a shorthand for
Vasat* v = [Vasat sharedInstance];
MyObj* o = [MyObj makeWithVasat:v];

Convience methods for CoreData include:

// all object types
NSFetchedResultsController* res = [MyObj selectAll];
// with predicate
NSFetchedResultsController* res = [MyObj selectWhere:[NSPredicate prediacteWithFormst:@"active=true"]];
// with predicate and sort
NSFetchedResultsController* res = [MyObj selectWhere:[NSPredicate prediacteWithFormst:@"active=true"] sortBy:@"dateMade" acending:true];
// with predicate and sort and group
NSFetchedResultsController* res = [MyObj selectWhere:[NSPredicate prediacteWithFormst:@"active=true"] sortBy:@"dateMade" acending:true groupBy:@"somefield"];
 
// category helper
NSArray* resAsArray = [res toArray];
  
// #### save and delete
 
MyObj* singleObj = [res firstObject];
  
// saving object
[singleObj saveLocal];
  
// deleting object

Properties and files

All VasatBaseModel objects have a collection of properties and files that can be specified.

// #### save and delete
 
MyObj* singleObj = [res firstObject];
  
// setting a property
[singleObj setProp:@"pname" value:@"val"];
id i = [singleObj getProp:@"pname"];
// setting files
[singleObj setFile:@"img.png" value:.. some NSURL ..];
 
NSURL* localURL = [singleObj getFile:@"image.png"];

Interactions with server

All vasat objects can intergrate with the server. This is done asyncronuslly and uses events from the Events System to get information back and forth.


VasatCollection* obj = [MyObj fetch];
[obj onOnce:VFEVENT_SYNC callBack:^(VasatCollection* res, NSError* e){
    if(e){
        // couldnt fetch from server
    }
    else{
        NSLog(@"Fetched %i entries",res.results.count);
    }
}];
  
// fetching with querey
[MyObj fetchWhere:@{@"active":@"true"}];
  
// saving to server
MyObj* singleObj = ...
[singeObj save];
  
// if you care about the servers response to a save
[singleObj onOnce:VFEVENT_SYNC callBack:^(VasatCollection* res, NSError* e){
    if(e){
        // couldnt save
    }
    else{
        NSLog(@"Saved %@",singleObj);
    }
}];
  
// Deleting from server
[singleObj delete];

Automatic syncing

Collections of objects can be synced both ways using the vasat object. Object types that are to be synced should be declared to the Vasat instance

Vasat* v = [Vasat sharedInstance];
  
[v registerClass:[MyObj class]];
  
// will fetch all objects of MyObj from the server, also if there are any local objects of type MyObj that have not successfully saved to the server it will send them.
[v sync];
  
// Sync since
[v syncSince:60*60]; // only sync if you havent synced in the last hour
  
// events
[v on:VFEVENT_VASAT_SYNC_STARTING callBack:^(VasatCollection* res, NSError* e){
    // show spinner
}];
[v on:VFEVENT_VASAT_SYNC callBack:^(VasatCollection* res, NSError* e){
    // hide spinner
    if(e){
        // couldnt sync
    }
    else{
        // this will list all the objects after the sync
        [MyObj selectAll];
    }
}];

Built in objects

Pre-defined objects in vasat mirror those on the server.

  • User
  • Device
  • PushRecipt

As well as a local only object called Session that maintains the active server session.

Events System

The Vasat iOS SDK has an events triggering system inspired by the js library backbone. There is an objective-c Catgegory that gives every NSObject class a 'trigger' and on, onOnce, listenTo and listenToOnce method.

'on' / 'onOnce' events

Works in the same manner as jquery in javascript. Run the block whenever the object triggers the matching event.

NSString* myStr = @"Any old object";
 
 
[myStr on:@"EVENT" callBack:^(id obj, NSError* err){
    NSLog(@"Trigger event called with obj %@ and error %@",obj,err);
}];
 
 
[myStr trigger:@"EVENT" withArg:@"my arg" error:nil];
 
 
// results: Trigger event called with obj my arg and error (null)

Memory Leak warning

Any block code supplied to an 'on' methods callback will be retained for as long as the object is alive. Using it on long lasting objects (eg the [ Vasat sharedInstance ] object) will mean the block and all its references are held in memory. For a safer method see the next section listenTo

'listenTo' / 'listenToOnce' events

Similar to the on method, listenTo will run the callback when an event for an object is trigger. The big difference between listenTo and on is a source object must be specified for a listenTo call. The callback for a listen to will be removed if the source object is dealloced.


@implementation MyViewController 
-(void)viewDidLoad{
    [super viewDidLoad];
    Vasat* v = [Vasat sharedInstance];
 
    [self listenTo:v event:VFEvent_VASAT_LOGOUT callBack:^(id obj, NSError* err){
        NSLog(@"Active user logged out");
    }];
 
}
@end

Memory Leak warning

When using blocks with references to self you can get a cyclic memory lock. Make sure any references to self in your block are done so via a weak reference.

Wrong ways

Using on with a strong reference to self will mean both the block and the self object are held for as long as the v object exists (which is forever).


@implementation MyViewController 
-(void)viewDidLoad{
    [super viewDidLoad];
    Vasat* v = [Vasat sharedInstance];
 
    [v on:VFEvent_VASAT_LOGOUT callBack:^(id obj, NSError* err){
        NSLog(@"Active user logged out");
        // viewController will pop, but dealloc will not get called since the V object is never dealloced & the block references self.
        [self.navigationController popViewController:true];
    }];
 
}
@end

Using a on with a weak reference. While this appears to be a better way, and will result in the self class being dealloced. The block will not be dealloced and will run if the LOGOUT event is ever called again. Since if its called more than one it will try and run a method on this this object (which will be dealloced after the first time) it will crash.


@implementation MyViewController 
-(void)viewDidLoad{
    [super viewDidLoad];
    Vasat* v = [Vasat sharedInstance];
    __weak MyViewController* this = self;
    [v on:VFEvent_VASAT_LOGOUT callBack:^(id obj, NSError* err){
        NSLog(@"Active user logged out");
        // since block references 'this' which is a weak reference, poping the stack will dealloc the MyViewController object. 
        // However, since the 'on' method was used, the block will not be removed from the list of callbacks. 
        // If the VFEvent_VASAT_LOGIN event it called a second time, this method will try to run on a deallocted object (crash)
        [this.navigationController popViewController:true];
    }];
 
}
@end

Using listenTo with a strong reference to self. Since the block references self, dealloc will never be called on the object. ListenTo will only remove a callback block one an object is dealloced so this code will leak.

@implementation MyViewController 
-(void)viewDidLoad{
    [super viewDidLoad];
    Vasat* v = [Vasat sharedInstance];
 
    [self listenTo:v event:VFEvent_VASAT_LOGOUT callBack:^(id obj, NSError* err){
        NSLog(@"Active user logged out");
        // viewController will pop, but dealloc will not get called since this block is stored in the listenTo queue for V, and the block references self.
        [self.navigationController popViewController:true];
    }];
 
}
@end

Right way

Using a listenTo and a weak reference to self will mean that the dealloc will get called on the ViewController, and listenTo will remove the block from the list of callbacks for the 'v' object once that happens.


@implementation MyViewController 
-(void)viewDidLoad{
    [super viewDidLoad];
    Vasat* v = [Vasat sharedInstance];
    __weak MyViewController* this = self;
    [self listenTo:v event:VFEvent_VASAT_LOGOUT callBack:^(id obj, NSError* err){
        NSLog(@"Active user logged out");
        // since block references 'this' which is a weak reference, poping the stack will dealloc the MyViewController object.
        [this.navigationController popViewController:true];
    }];
 
}
@end