iosobjective-cswiftxcodeon-demand-resources

Unable to find On-Demand Resources embedded in App bundle


I use URLForResource to find on-demand resources after downloading them and it currently works correctly.

Due to some issues with Apple not being able to download the ODR during their review, I now have to temporarily embed my On-Demand Resources AssetPacks in the App Bundle changing in XCode "Embed Asset Packs In Product Bundle" from false to true.

The problem is that after doing that when I use the same URLForResource method it now returns null.

NSURL *myDirectoryURL = [[NSBundle mainBundle] URLForResource:targetFolder withExtension:@""];

Since they become part of the product bundle am I not supposed to be able to find them in that way?


UPDATE: Some (ugly) working code from a non-iOS dev working on a Cordova plugin.. :)

    NSLog(@"[odr] calling nsbrr conditionallyBeginAccessingResourcesWithCompletionHandler..");
    @try
    {
      [odrRequest conditionallyBeginAccessingResourcesWithCompletionHandler:^(BOOL resourcesAvailable) {
        if (resourcesAvailable) {
          NSLog(@"[odr] already available (in-bundle) / downloaded.");
          @try
          {
            NSURL *myDirectoryURL = [[NSBundle mainBundle] URLForResource:targetFolder withExtension:@""];
            NSLog(@"[odr] Target directory URL: '%@'", myDirectoryURL);
            NSString *res = myDirectoryURL.absoluteString;
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:res];
            NSLog(@"[odr] path found, returning it in callback: '%@'", res);
            [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
          }
          @catch(id anException) {
            NSString *errMsg = @"Error in path detection or calling callback (in already-downl-odr handler): ";
            errMsg = [errMsg stringByAppendingString:anException];
            NSLog(@"[odr] Exception: '%@'", errMsg);
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errMsg];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
          }
        } else {
          NSLog(@"[odr] Starting to load (in-bundle) / download..");
          @try
          {
            [odrRequest beginAccessingResourcesWithCompletionHandler:^(NSError * _Nullable error) {
              if (error == nil) {
                NSLog(@"[odr] File load / download success.");
                @try
                {
                  NSURL *myDirectoryURL = [[NSBundle mainBundle] URLForResource:targetFolder withExtension:@""];
                  NSLog(@"[odr] Target directory URL: '%@'", myDirectoryURL);
                  NSString *res = myDirectoryURL.absoluteString;
                  pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:res];
                  NSLog(@"[odr] path found, returning it in callback: '%@'", res);
                  [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
                }
                @catch(id anException) {
                // ...


Solution

  • The fact that you are sidestepping the use of the server as a source of the ODR download by embedding the on-demand resources changes nothing about how you access them. You still have to have an NSBundleResourceRequest and call beginAccessingResourcesWithCompletionHandler: and access the resources in the completion handler, exactly as you would do if you hadn't turned on Embed Asset Packs In Product Bundle.

    So your code should be unchanged, without regard to the value of Embed Asset Packs In Product Bundle. If the same code works when Embed Asset Packs In Product Bundle is NO but not when it is YES, your code was wrong to start with.