How should I do it to handle the data which I got by "long-lived operations" when application is not running?

Please let questions about "The CloudKit framework introduces support for long-lived operations" is described in the "What's New in iOS 9.3".
(https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9_3.html#//apple_ref/doc/uid/TP40016661-SW1)

I did the following operations.

1. I uploaded a dummy file of approximately 100MB to "PUBLIC DATABASE" > "Default Zone" in the "CloudKit Dashboard".
2. I created the iOS app for the test, such as the following.
2-1. Setting CKOperation.longLived to YES.
2-2. Gettng the uploaded dummy files using the CKFetchRecordsOperation object.
2-3. In order to confirm that the CompletionBlock of CKFetchRecordsOperation has been called, saving the log to UserDefaults.
3. I using the iOS app ("2"), it has got the file by CKFetchRecordsOperation object.
4. Before the getting of the file is completed, I exit the app by swiping up in the "App Switcher".

After you exit the app, I confirmed that the application capacity is increasing.
(I saw "Settings" > "General" > "Storage & Cloud Usage" > "STORAGE" > "Manage Storage")
Therefore, I think the file was got by "long-lived operations".
However, CompletionBlock does not seem to be called then. Because nothing has been saved in UserDefaults.
How should I do it to handle the data which I got when application is not running?

The following is the code of the test application.

----------
- (IBAction)test:(id)sender {

CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:OSSRecordId];
NSArray *fetchRecordIDs = [[NSArray alloc] initWithObjects:recordID, nil];
CKFetchRecordsOperation *fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs:fetchRecordIDs];
// Record fetch completed
fetchRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record,
CKRecordID *recordID, NSError *error) {
// User Defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *defaultsValue = [defaults objectForKey:OSSUserDefaultsKeyRecordID];
NSString *string = [NSString stringWithFormat:@"%@/%@", defaultsValue, recordID.recordName];
[defaults setObject:string forKey:OSSUserDefaultsKeyRecordID];
};

// All fetch completed
fetchRecordsOperation.fetchRecordsCompletionBlock = ^(NSDictionary
*recordsByRecordID, NSError *error) {
// User Defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *defaultsValue = [defaults objectForKey:OSSUserDefaultsKeyRecordID];
NSString *string = [NSString stringWithFormat:@"%@/%s", defaultsValue, "fetchRecordsCompletionBlock"];
[defaults setObject:string forKey:OSSUserDefaultsKeyRecordID];
};

// Long-Lived
fetchRecordsOperation.longLived = YES;
fetchRecordsOperation.longLivedOperationWasPersistedBlock = ^() {
// User Defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *defaultsValue = [defaults objectForKey:OSSUserDefaultsKeyRecordID];
NSString *string = [NSString stringWithFormat:@"%@/%s", defaultsValue, "longLivedOperationWasPersistedBlock"];
[defaults setObject:string forKey:OSSUserDefaultsKeyRecordID];
};
fetchRecordsOperation.database = [[CKContainer defaultContainer] publicCloudDatabase];

[fetchRecordsOperation start];
}
----------

I built application by official release of Xcode 7.3, And I ran application in official release of iOS 9.3.
I have modified the code with reference to the CKOperation Class Reference(https://developer.apple.com/library/ios/documentation/CloudKit/Reference/CKOperation_class/index.html).
However, the result was the same.


The versions that I confirmed are as follows.


<iOS 9.3>
Builds: 13E233, 13E234
Posted Date: Mar 21, 2016


<Xcode 7.3>
Build: 7D175
Posted Date: Mar 21, 2016


The following is the code of the test application.


- (IBAction)test:(id)sender {
    NSLog(@"%s", __FUNCTION__);

    CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:OSSRecordId];
    NSArray *fetchRecordIDs = [[NSArray alloc] initWithObjects:recordID, nil];
    CKFetchRecordsOperation *fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs:fetchRecordIDs];

    fetchRecordsOperation.longLived = YES;

    // Record fetch completed
    fetchRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record,
                                                       CKRecordID *recordID, NSError *error) {
        // User Defaults
        NSString *message = [NSString stringWithFormat:@"%@:%@", @"perRecordCompletionBlock", recordID.recordName];
        [self setUserDefault:message];
    };

    // All fetch completed
    fetchRecordsOperation.fetchRecordsCompletionBlock = ^(NSDictionary
                                                          *recordsByRecordID, NSError *error) {
        // User Defaults
        [self setUserDefault:@"fetchRecordsCompletionBlock"];
    };

    // Long-Lived
    fetchRecordsOperation.longLivedOperationWasPersistedBlock = ^() {
        NSLog(@"longLivedOperationWasPersistedBlock");

        // User Defaults
        [self setUserDefault:@"longLivedOperationWasPersistedBlock"];
    };
    fetchRecordsOperation.database = [[CKContainer defaultContainer] publicCloudDatabase];


    // Fetcing Long-Lived Operations
    [[CKContainer defaultContainer] fetchLongLivedOperationWithID:fetchRecordsOperation.operationID
                                                completionHandler:^(CKOperation *outstandingOperation,
                                                                    NSError *error)
     {
         // User Defaults
         NSString *message = [NSString stringWithFormat:@"%@ outstandingOperation:%@ error:%@",
                              @"fetchLongLivedOperationWithID", outstandingOperation, error];
         [self setUserDefault:message];
     }];

    [[CKContainer defaultContainer] fetchAllLongLivedOperationIDsWithCompletionHandler:^(NSArray<NSString *> *outstandingOperationIDs, NSError *error)
     {
         // User Defaults
         NSString *message = [NSString stringWithFormat:@"%@ outstandingOperationsByIDs:%@ error:%@",
                              @"fetchAllLongLivedOperationsWithCompletionHandler", outstandingOperationIDs, error];
         [self setUserDefault:message];
     }];

    [fetchRecordsOperation start];
}
// User Default
- (void)setUserDefault:(NSString *)message {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *defaultsValue = [defaults objectForKey:OSSUserDefaultsKeyRecordID];
    NSString * string;
    if (defaultsValue) {
        string = [NSString stringWithFormat:@"%@/%@", defaultsValue, message];
    } else {
        string = message;
    }
    [defaults setObject:string forKey:OSSUserDefaultsKeyRecordID];
}

Problem resolved.

What I missed was to add the operation to operation queue at last.

How should I do it to handle the data which I got by "long-lived operations" when application is not running?
 
 
Q