On Demand Resources from Xcode Server Not Loading

Problem


Simple ODR-enabled app built with a Xcode Server Bot does not have resources accessible to it even though conditionallyBeginAccessingResourcesWithCompletionHandler and beginAccessingResourcesWithCompletionHandler indicate success. In fact, conditionallyBeginAccessingResourcesWithCompletionHandler calls back with a true value for resourcesAvailable even if an invalid tag is specified!


Platform: Mac OS X El Capitan GM, Xcode 7 GM, Xcode Server 5 Beta


Steps:


1. Create a new Project and use the Single View Application template for Swift

2. Make sure Enable On Demand Resources is Yes in Build Settings for app target

3. Add one JPG named, Image.jpg, to the project and give it the tag, TheODRTag

4. Change the contents of ViewController.swift to the following:

    private var request: NSBundleResourceRequest!

    override func viewDidLoad() {
        super.viewDidLoad()

        request = NSBundleResourceRequest(tags: Set<String>(["TheODRTag"]))
        request.conditionallyBeginAccessingResourcesWithCompletionHandler { [unowned self] resourcesAvailable in
            if resourcesAvailable {
                self.loadImage()
                return
            }
            self.request.beginAccessingResourcesWithCompletionHandler { error in
                if error == nil {
                    self.loadImage()
                }
            }
        }
    }

    private func loadImage() {
        dispatch_async(dispatch_get_main_queue()) { [unowned self] in
            let imageView = UIImageView(frame: CGRectZero)
            imageView.contentMode = .ScaleAspectFill
            imageView.image = UIImage(named: "Image.jpg")
            imageView.translatesAutoresizingMaskIntoConstraints = false
            self.view.addSubview(imageView)
            self.view.addConstraint(imageView.topAnchor.constraintEqualToAnchor(self.view.topAnchor))
            self.view.addConstraint(imageView.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor))
            self.view.addConstraint(imageView.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor))
            self.view.addConstraint(imageView.bottomAnchor.constraintEqualToAnchor(self.view.bottomAnchor))
        }
    }

5. Run on device from Xcode, note the image is loaded

6. Create a Bot on Xcode Server using the default options and no triggers

7. Run the bot and note that it succeeds after "uploading on demand resources"

8. Install the app on-device from Xcode Server's Web interface

9. Run the app, note the image is not loaded. Adding debug messages and/or alerts shows that conditionallyBeginAccessingResourcesWithCompletionHandler erroneously indicates the resources are available, even on the first run.


What did I miss?

Thanks!

Replies

I'm new to Xcode so I bought a book.


One of the things it said was that Xcode does not like JPEG images - use .PNG instead.


Hope this helps - I'm still having trouble writing an app that says "Hello", so I'm certainly not an expert - just passing on info.

Update:



The Xcode bot appears to have gotten the protocol, port, and path to the assetpack wrong with very little (if any) deviation from the default settings for both Xcode Server and a ODR-enabled Xcode project.

I'm seeing the same thing. To see if it was a problem with the set up or with the code, I tried it using DemoBots, which should be set up for ODR. When I install the application from the server, it runs, but then crashes on the main screen. The device console show warnings such as

CoreUI: CUICatalog can't locate asset pack 'com.example.apple-samplecode.DemoBots.asset-pack-0RZCL64GOVN31' for bundle 'NSBundle </var/mobile/Containers/Bundle/Application/A235735F-E98A-40AA-A6B5-31132293CB3A/DemoBots.app> (loaded)'

Does anyone have any more info on this?


I've just had this issue begin happening out of the blue, on a project where On Demand Resources were working before. That is, conditionallyBeginAccessingResourcesWithCompletionHandler indicates success, but the resources are not there, and the disk menu in the debugger doesn't show any tags available.

Hi!


Maybe my issue is somehow related to the issues you are talking about.

I am using iOS 9.3.1 and Xcode 7.3. I use Xcode as the host of my ODR content (no testflight, no Xcode server, no custom server).

I have the same result both on device and simulator described below.

I can see and manage my ODR tags at runtime with the Disk gauge.


For test purposes I have an image tag consisting of 3 images. It is not initial or prefetched tag but regular ODR tag.

I use conditionallyBeginAccessingResourcesWithCompletionHandler method to get tag(s) availability.

After the first install it obviously returns false, and thus I call beginAccessingResourcesWithCompletionHandler method that completes successfully.

After this I can access an image (of the downloaded tag) by calling [UIImage imageNamed:] method.


Suprisingly when I want to access another image from the previously downloaded tag the following happen:

- I got TRUE return value from conditionallyBeginAccessingResourcesWithCompletionHandler ( - this is what I expect)

- the [UIImage imageNamed:] returns nil !!!

- if I call the [UIImage imageNamed:] multiple times in a row (like infinite loop), at the first call I got the following error line 3 times in the log:

"CUIThemeStore: No theme registered with id=x" (x might vary)

- all subsequent (2nd and after) imageNamed: calls result this log:

CoreUI: CUICatalog can't locate asset pack 'xxxxxxxxxx.asset-pack-00000008K1FYR' for bundle 'NSBundle </Users/xxxxxxxx/Library/Developer/CoreSimulator/Devices/xxxxxxxxxxx/data/Containers/Bundle/Application/xxxxxxxx/xxxxxxx.app> (loaded)'

- If I repeat the use case trying to access this same image I have success with UIImage's imageNamed method. Obviously it is scheduled later in the run loop and thus some ODR related backround tasks might have completed till that time.


Any idea how to avoid/prevent this kind of error? It seems a framework bug since imageNamed should work in the completion block of conditionallyBeginAccessingResourcesWithCompletionHandler method call.


Thanks in advance!

... As further tests show: the image become accessible by imageNamed if I repeat the call via dispatch_async.

This is a workaround... It should be fixed by Apple...

CoreUI: CUICatalog can't locate asset pack 'asset-pack' for bundle 'NSBundle </var/containers/Bundle/Application/app> (loaded)'


conditionallyBeginAccessingResourcesWithCompletionHandler


returns true as resourcesAvailable, but


[UIImage imageNamed:]


returns nil