diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
index 78ea6764b45eddca1fdd1c95a5e2fbaa1312e0b6..222f7247ccc180fed9a1137f66945e6feb6a54df 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h
@@ -24,6 +24,26 @@
 #import <Foundation/Foundation.h>
 #import "CISDOBShared.h"
 
+//
+// The names of the notifications posted by the service manager
+//
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillLoginNotification;
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidLoginNotification;
+
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification;
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification;
+
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillDrillOnEntityNotification;
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidDrillOnEntityNotification;
+
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillRetrieveDetailsForEntityNotification;
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidRetrieveDetailsForEntityNotification;
+
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillSynchEntitiesNotification;
+FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidSynchEntitiesNotification;
+
+
+
 @class CISDOBIpadService, CISDOBAsyncCall, CISDOBIpadEntity;
 /**
  * \brief A class that manages a connection to the openBIS iPad service, caching data locally as CISDOBIpadEntity objects.
diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
index c47d11fe71a9a0ee581bc591628b3832b7a4ac77..1abd1837bdc8c453dd146c3668c31f4e2c7e10b9 100644
--- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
+++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m
@@ -21,21 +21,40 @@
 //
 //
 
+
 #import "CISDOBIpadServiceManager.h"
 #import "CISDOBIpadService.h"
 #import "CISDOBIpadEntity.h"
 #import "CISDOBConnection.h"
 #import "CISDOBAsyncCall.h"
 
+NSString *const CISDOBIpadServiceWillLoginNotification = @"CISDOBIpadServiceWillLoginNotification";
+NSString *const CISDOBIpadServiceDidLoginNotification = @"CISDOBIpadServiceDidLoginNotification";
+NSString *const CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification = @"CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification";
+NSString *const CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification = @"CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification";
+NSString *const CISDOBIpadServiceWillDrillOnEntityNotification = @"CISDOBIpadServiceWillDrillOnEntityNotification";
+NSString *const CISDOBIpadServiceDidDrillOnEntityNotification = @"CISDOBIpadServiceDidDrillOnEntityNotification";
+NSString *const CISDOBIpadServiceWillRetrieveDetailsForEntityNotification = @"CISDOBIpadServiceWillRetrieveDetailsForEntityNotification";
+NSString *const CISDOBIpadServiceDidRetrieveDetailsForEntityNotification = @"CISDOBIpadServiceDidRetrieveDetailsForEntityNotification";
+NSString *const CISDOBIpadServiceWillSynchEntitiesNotification = @"CISDOBIpadServiceWillSynchEntitiesNotification";
+NSString *const CISDOBIpadServiceDidSynchEntitiesNotification = @"CISDOBIpadServiceDidSynchEntitiesNotification";
+
 // Internal service call that includes the private state
 @interface CISDOBIpadServiceManagerCall : CISDOBAsyncCall
 
 @property(weak) CISDOBIpadServiceManager *serviceManager;
 @property(nonatomic) CISDOBAsyncCall *serviceCall;
+@property(copy) NSString *willCallNotificationName;
+@property(copy) NSString *didCallNotificationName;
+
+@property(nonatomic) BOOL sendSynchNotifications;
 
 // Initialization
 - (id)initWithServiceManager:(CISDOBIpadServiceManager *)serviceManager serviceCall:(CISDOBAsyncCall *)call;
 
+- (void)notifySuccess:(id)result;
+- (void)notifyFailure:(NSError *)error;
+
 @end
 
 // Internal class that synchronizes result data to the managed object context
@@ -112,11 +131,19 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
 - (void)syncEntities:(NSArray *)rawEntities pruning:(BOOL)prune notifying:(CISDOBIpadServiceManagerCall *)managerCall
 {
     void (^syncBlock)(void) = ^{
+        if (managerCall.didCallNotificationName) {
+            [[NSNotificationCenter defaultCenter] postNotificationName: managerCall.didCallNotificationName object: self];
+        }
+        
+        [[NSNotificationCenter defaultCenter] postNotificationName: CISDOBIpadServiceWillSynchEntitiesNotification object: self];
+        
         // Run the synchronizer in the background thread
         CISDOBBackgroundDataSynchronizer *synchronizer = [[CISDOBBackgroundDataSynchronizer alloc] initWithServiceManager: self managerCall: managerCall rawEntities: rawEntities];
         synchronizer.prune = prune;
         [synchronizer run];
         
+        [[NSNotificationCenter defaultCenter] postNotificationName: CISDOBIpadServiceDidSynchEntitiesNotification object: self];         
+        
         void (^notifyBlock)(void) = ^ {
             // Save the MOC and notifiy the client on the main thread
             CISDOBBackgroundDataSynchronizer *notifySynchronizer = synchronizer;
@@ -154,26 +181,50 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
 
 - (CISDOBAsyncCall *)loginUser:(NSString *)user password:(NSString *)password
 {
-    return [self.service loginUser: user password: password];
+    CISDOBAsyncCall *call = [self.service loginUser: user password: password];
+    CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call pruning: NO];
+    call.success = ^(id result) { [managerCall notifySuccess: result]; };
+    managerCall.willCallNotificationName = CISDOBIpadServiceWillLoginNotification;
+    managerCall.didCallNotificationName = CISDOBIpadServiceDidLoginNotification;
+    managerCall.sendSynchNotifications = NO;
+    return managerCall;
 }
 
 - (CISDOBAsyncCall *)retrieveRootLevelEntities
 {
     CISDOBAsyncCall *call = [self.service listRootLevelEntities];
         // get rid of entities not mentioned in the original call
-    return [self managerCallWrappingServiceCall: call pruning: YES];
+    CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call pruning: YES];
+    
+    managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification;
+    managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification;
+    managerCall.sendSynchNotifications = YES;
+    
+    return managerCall;
 }
 
 - (CISDOBAsyncCall *)drillOnEntity:(CISDOBIpadEntity *)entity
 {
     CISDOBAsyncCall *call = [self.service drillOnEntityWithPermId: entity.permId refcon: entity.refcon];
-    return [self managerCallWrappingServiceCall: call];
+    CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call];
+    
+    managerCall.willCallNotificationName = CISDOBIpadServiceWillDrillOnEntityNotification;
+    managerCall.didCallNotificationName = CISDOBIpadServiceDidDrillOnEntityNotification;
+    managerCall.sendSynchNotifications = YES;
+    
+    return managerCall;
 }
 
 - (CISDOBAsyncCall *)detailsForEntity:(CISDOBIpadEntity *)entity
 {
     CISDOBAsyncCall *call = [self.service detailsForEntityWithPermId: entity.permId refcon: entity.refcon];
-    return [self managerCallWrappingServiceCall: call];
+    CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call];
+    
+    managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveDetailsForEntityNotification;
+    managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveDetailsForEntityNotification;
+    managerCall.sendSynchNotifications = YES;
+    
+    return managerCall;
 }
 
 - (NSArray *)allIpadEntitiesOrError:(NSError **)error;
@@ -234,8 +285,32 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
     return self;
 }
 
+- (void)sendCompletionNotification
+{
+    if (self.sendSynchNotifications) {
+        // This is handled elsewhere
+    } else if (self.didCallNotificationName) {
+        [[NSNotificationCenter defaultCenter] postNotificationName: self.didCallNotificationName object: self.serviceManager];
+    }
+}
+
+- (void)notifySuccess:(id)result
+{
+    if (self.success) self.success(result);
+    [self sendCompletionNotification];
+}
+
+- (void)notifyFailure:(NSError *)error
+{
+    if (self.fail) self.fail(error);
+    [self sendCompletionNotification];
+}
+
 - (void)start
 {
+    if (self.willCallNotificationName) {
+        [[NSNotificationCenter defaultCenter] postNotificationName: self.willCallNotificationName object: self.serviceManager];
+    }
     [_serviceCall start];
 }
 
@@ -316,9 +391,9 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl
 - (void)notifyCallOfResult:(id)args
 {
     if (self.error) {
-        self.managerCall.serviceCall.fail(self.error);
+        [self.managerCall notifyFailure: self.error];
     } else if (self.managerCall.success) {
-        self.managerCall.success(self.rawEntities);
+        [self.managerCall notifySuccess: self.rawEntities];
     }
     
 }
diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.h b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.h
index 9f94f9e2251c2e12c47d6040b92e031ca57db4ed..6d61184aa9489ae8168f75538744c6d54d604daa 100644
--- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.h
+++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.h
@@ -28,4 +28,21 @@
 
 @property(strong) CISDOBIpadServiceManager *serviceManager;
 
+// Tracking Notifications
+@property(nonatomic) BOOL willLogin;
+@property(nonatomic) BOOL didLogin;
+
+
+@property(nonatomic) BOOL willRetrieveRootLevel;
+@property(nonatomic) BOOL didRetrieveRootLevel;
+
+@property(nonatomic) BOOL willSynchEntities;
+@property(nonatomic) BOOL didSynchEntities;
+
+@property(nonatomic) BOOL willDrill;
+@property(nonatomic) BOOL didDrill;
+
+@property(nonatomic) BOOL willRetrieveDetails;
+@property(nonatomic) BOOL didRetrieveDetails;
+
 @end
diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
index 31e6efbb7ee0e345fdb0aa0b9641bb76de455c45..d8244a0fbc4889490175cc28eaeb31c21c38d584 100644
--- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
+++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m
@@ -29,6 +29,72 @@
 
 @implementation CISDOBIpadServiceManagerTest
 
+- (void)processNotification:(NSNotification *)note
+{
+    if ([CISDOBIpadServiceWillLoginNotification isEqualToString: [note name]]) {
+        self.willLogin = YES;
+    }
+    if ([CISDOBIpadServiceDidLoginNotification isEqualToString: [note name]]) {
+        self.didLogin = YES;
+    }
+    if ([CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification isEqualToString: [note name]]) {
+        self.willRetrieveRootLevel = YES;
+    }
+    if ([CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification isEqualToString: [note name]]) {
+        self.didRetrieveRootLevel = YES;
+    }
+    if ([CISDOBIpadServiceWillSynchEntitiesNotification isEqualToString: [note name]]) {
+        self.willSynchEntities = YES;
+    }
+    if ([CISDOBIpadServiceDidSynchEntitiesNotification isEqualToString: [note name]]) {
+        self.didSynchEntities = YES;
+    }
+    if ([CISDOBIpadServiceWillDrillOnEntityNotification isEqualToString: [note name]]) {
+        self.willDrill = YES;
+    }
+    if ([CISDOBIpadServiceDidDrillOnEntityNotification isEqualToString: [note name]]) {
+        self.didDrill = YES;
+    }
+    if ([CISDOBIpadServiceWillRetrieveDetailsForEntityNotification isEqualToString: [note name]]) {
+        self.willRetrieveDetails = YES;
+    }
+    if ([CISDOBIpadServiceDidRetrieveDetailsForEntityNotification isEqualToString: [note name]]) {
+        self.didRetrieveDetails = YES;
+    }    
+}
+
+- (void)registerForNotifications
+{
+    self.willLogin = NO;
+    self.didLogin = NO;
+    
+    self.willRetrieveRootLevel = NO;
+    self.didRetrieveRootLevel = NO;
+    self.willSynchEntities = NO;
+    self.didSynchEntities = NO;
+
+    self.willDrill = NO;
+    self.didDrill = NO;
+
+    self.willRetrieveDetails = NO;
+    self.didRetrieveDetails = NO;
+    
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    [notificationCenter
+        addObserverForName: nil
+        object: self.serviceManager
+        queue: [NSOperationQueue mainQueue]
+        usingBlock: ^(NSNotification *note) {
+            [self processNotification: note];
+        }];
+}
+
+- (void)unregisterForNotifications
+{
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    [notificationCenter removeObserver: self];
+}
+
 - (void)setUp
 {
     [super setUp];
@@ -38,10 +104,13 @@
     NSError *error;
     self.serviceManager = [[CISDOBIpadServiceManager alloc] initWithStoreUrl: databaseUrl openbisUrl: url trusted: YES error: &error];
     STAssertNotNil(self.serviceManager, @"Service Manager file could not be created:\n%@", error);
+
+    [self registerForNotifications];
 }
 
 - (void)tearDown
 {
+    [self unregisterForNotifications];
     [[NSFileManager defaultManager] removeItemAtURL: self.serviceManager.storeUrl error: nil];
     [super tearDown];
 }
@@ -86,14 +155,71 @@
 
 }
 
+- (void)assertNotLoggedIn
+{
+    STAssertFalse(self.willLogin, @"Should not be logged in yet");
+    STAssertFalse(self.didLogin, @"Should not be logged in yet");
+}
+
+- (void)assertLoggedIn
+{
+    STAssertTrue(self.willLogin, @"Should be logged in.");
+    STAssertTrue(self.didLogin, @"Should be logged in.");
+}
+
+- (void)assertBeforeRootLevelCall
+{
+    STAssertFalse(self.willRetrieveRootLevel, @"Should not have retrieved root level");
+    STAssertFalse(self.didRetrieveRootLevel, @"Should not have retrieved root level");
+    STAssertFalse(self.willSynchEntities, @"Should not have processed root level");
+    STAssertFalse(self.didSynchEntities, @"Should not have processed root level");
+}
+
+- (void)assertAfterRootLevelCall
+{
+    STAssertTrue(self.willRetrieveRootLevel, @"Should have retrieved root level");
+    STAssertTrue(self.didRetrieveRootLevel, @"Should have retrieved root level");
+    STAssertTrue(self.willSynchEntities, @"Should have processed root level");
+    STAssertTrue(self.didSynchEntities, @"Should have processed root level");
+}
+
+- (void)assertBeforeDrill
+{
+    STAssertFalse(self.willDrill, @"Should not have drilled");
+    STAssertFalse(self.didDrill, @"Should not have drilled");
+}
+
+- (void)assertAfterDrill
+{
+    STAssertTrue(self.willDrill, @"Should have drilled");
+    STAssertTrue(self.didDrill, @"Should have drilled");
+}
+
+- (void)assertBeforeDetails
+{
+    STAssertFalse(self.willRetrieveDetails, @"Should not have retrieved details");
+    STAssertFalse(self.didRetrieveDetails, @"Should not have retrieved details");
+}
+
+- (void)assertAfterDetails
+{
+    STAssertTrue(self.willRetrieveDetails, @"Should have retrieved details");
+    STAssertTrue(self.didRetrieveDetails, @"Should have retrieved details");
+}
+
 - (void)testPersistEntities
 {
     CISDOBAsyncCall *call;
+    
+    [self assertNotLoggedIn];
     call = [self.serviceManager loginUser: GetDefaultUserName() password: GetDefaultUserPassword()];
     [self configureAndRunCallSynchronously: call];
+    [self assertLoggedIn];
     
+    [self assertBeforeRootLevelCall];
     call = [self.serviceManager retrieveRootLevelEntities];
     [self configureAndRunCallSynchronously: call];
+    [self assertAfterRootLevelCall];
     
     STAssertNotNil(_callResult, @"The service manager should have returned some entities.");
 
@@ -101,14 +227,21 @@
     NSArray *entitiesWithChildren = [self entitiesWithChildren];
     STAssertTrue([entitiesWithChildren count] > 0, @"There should be some entities with children");
    
+
+    [self assertBeforeDrill];
     call = [self.serviceManager drillOnEntity: [entitiesWithChildren objectAtIndex: 0]];
     [self configureAndRunCallSynchronously: call];
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
+    [self assertAfterDrill];
+   
     
     // Get detail information on some entities
+    [self assertBeforeDetails];
     call = [self.serviceManager detailsForEntity: [entitiesWithChildren objectAtIndex: 1]];
     [self configureAndRunCallSynchronously: call];
     STAssertNotNil(_callResult, @"The iPad service should have returned some entities.");
+    [self assertAfterDetails];
+  
 
     
     // Check that the children could be found