2

I have a strange problem which I can't seem to solve on my own. Any help or thought is appreciated.

The problem:

  • NSMetadataQuery finds normal files (like test.txt) but no filewrapper bundle (myWrapperDocument.pro)
  • However, NSFileManager finds all files in my ubiquity container - so the files are there, but NSMetadataQuery doesn't find them!

The facts:

  • UIDocument based app using NSFileWrappers
  • Shared Ubiquity Container (for iOS and Desktop app)
  • Works perfect on Mac OS
  • Works perfect on my iPad Mini and my iPhone 4S and iPhone 3GS (running iOS6 and iOS5)
  • Doesn't work on my iPad1 nor on most of my beta tester's devices (iPads 1,2&3 running iOS5 or 6)

What I did so far:

  • Studied WWDC12 UIDocument & iCloud example (CloudNotes.xcodeproj)
  • Studied hours in Apple's dev forum and here, unfortunately without any luck
  • Tested many different predicates, checked the entitlements and the document setup (so the system knows, that it's not a folder, but a document bundle)
  • Clearing and resetting the Ubiquity container

The relevant code:

Entitlements should be correct; Info.plist document setup ( I think the document type has been registered correctly )

<key>CFBundleDocumentTypes</key>
    <array>
  <dict>
      <key>CFBundleTypeExtensions</key>
      <array>
        <string>pro</string>
      </array>
      <key>CFBundleTypeName</key>
      <string>Prowriting Sketch</string>
      <key>LSItemContentTypes</key>
      <array>
        <string>de.ac.prowriting.sketch</string>
      </array>
      <key>LSTypeIsPackage</key>
      <true/>
  </dict>

  …

  <key>UTExportedTypeDeclarations</key>
    <array>
    <dict>
      <key>CFBundleTypeExtensions</key>
      <array>
        <string>pro</string>
      </array>
      <key>LSTypeIsPackage</key>
      <true/>
      <key>UTTypeConformsTo</key>
      <array>
        <string>com.apple.package</string>
      </array>
      <key>UTTypeDescription</key>
      <string>Prowriting Sketch</string>
      <key>UTTypeIdentifier</key>
      <string>de.ac.prowriting.sketch</string>
    </dict>

The ubiquity container and iCloud documents url are all fine, this is how I set up the query:

- (void)startMetadataQuery {
  // ...
  [self.query setSearchScopes:@[NSMetadataQueryUbiquitousDocumentsScope]];

  // search for all .pro documents, also tried other predicates, see below
  NSString *predicate = [NSString stringWithFormat:@"%K like '*'"];
  [self.query setPredicate:[NSPredicate predicateWithFormat:predicate, NSMetadataItemFSNameKey]];

  // register observer (...)
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishMetadataQuery:) name:NSMetadataQueryDidFinishGatheringNotification object:nil];

  [self.query startQuery];
}

- (void)didFinishMetadataQuery:(NSNotification*)notification {
    [self.query disableUpdates];
    NSLog(@"+++ found %i results: \n%@", self.query.resultCount, self.query.results);
    NSLog(@"+++ Results in iCloud folder: %i", [self.fileManager contentsOfDirectoryAtPath:self.iCloudDocumentsFolder.path error:nil].count);
}

The really strange thing is, that the query returns with just one file "test.txt", but the others remain undetected. But as you can see from the log, the container has 84 .pro files (all called "something.pro"), but the query only finds the one "test.txt".

Unfortunately accessing these files with NSFileManager isn't an option, as I don't seem to have the rights to read those. I don't think my container's corrupt as this issue also happens on fresh installations of my beta tester's devices?

2013-02-18 +++ found 1 results: ("<NSMetadataItem: 0x3ac390> /private/var/mobile/Library/Mobile Documents/ABCD123456~de~ac~prowriting/Documents/test.txt")
2013-02-18 +++ Results in iCloud folder: 84

I think it's the predicate, but:

@"%K like '*.pro*'"                // returns nothing
@"%%K like '*.*'"                  // returns only the test.txt file
@"%%K like '*'"                    // returns only the test.txt file
@"%K LIKE *"                       // returns only the test.txt file
@"NSMetadataItemFSNameKey == '*'"  // returns only the test.txt file

I really don't know what to do anymore. The most strange thing is, that it works on some devices while not working at all on other devices.

I would be super thankful for any hint on this issue. Thanks a lot!

auco
  • 9,329
  • 4
  • 47
  • 54
  • 1
    If you go to https://developer.icloud.com/#documents does the package show up and/or download as a package? If you change your predicate to search for "foo.pro" (an actual file) does that work? – Mike M Feb 19 '13 at 17:08
  • Yes, the packages show and they show as files, not folders. Foo.pro is not found (but foo.txt is). Also, not all devices are affected, on some it works perfect, on others not at all. I think it must have something to do with the FileWrapper/folder: my guess is a conflict between NSMetadataQuery not reporting folders and at the same time ignoring the contents of these folders because they're registered as bundle. If the bundle weren't registered correctly, I'd expect to get the wrappers contents listed, but that's not the case either. – auco Feb 20 '13 at 17:46
  • Not sure what the issue could be. I have an implementation of a package/folder that works fine. Using %K == foo.pro as a predicate would work for me – Mike M Feb 20 '13 at 18:55
  • and do you also have a shared ubiquitous document folder or are you using the "default" one? – auco Feb 20 '13 at 19:12
  • I use the one returned by [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; In my case I search for the entire file path to avoid duplicates, but searching for the name only works as well. – Mike M Feb 20 '13 at 19:20
  • I **think** I might be on to something: Because I developed on the Mac as well, my system set the bundle id, so all documents of type .pro appeared as file. Apparently I had one wrong document UTI entry; not sure if it was an additional Document Content Type UTI in the Document types setting or if it was a missing UTTypeTagSpecification (had CFBundleTypeExtensions) in the Exported Type UTIs. Lets see what my beta testers say. Can you find something fishy in the plist.info snippet above? – auco Feb 20 '13 at 20:58
  • I do use UTTypeTagSpecification where you use CFBundleTypeExtensions in the UTExportedTypeDeclarations. it's a dictionary with public.filename-extension and pro - good luck :) – Mike M Feb 20 '13 at 21:20
  • Do you have by any chance a LSItemContentType set in CFBundleDocumentTypes? I think it works if I remove this setting... – auco Feb 20 '13 at 22:41
  • 1
    in the first iCloud project I worked on I had an LSItemContentType. In my latest project I don't have LSItemContentType or CFBundleDocumentTypes either. FWIW, I ran across this link about debugging/clearing UTI's. http://www.cocoanetics.com/2012/09/fun-with-uti/ – Mike M Feb 21 '13 at 00:22

2 Answers2

2

strangely enough, I had to remove the LSItemContentTypes setting from the info.plist file:

<key>LSItemContentTypes</key>
  <array>
    <string>de.ac.prowriting.sketch</string>
  </array>

this setting was the reason, why my exported custom UTI filewrapper filetype was not recognized properly as file, but interpreted as folder. NSMetadataQuery does not query folders, that's why it didn't find any of my files.

Unfortunately I also have a Mac app and my custom filetype was registered correctly on the desktop affecting the Mobile Documents iCloud folder; so that was the reason why it worked on most of my devices, but on none of my testers.

auco
  • 9,329
  • 4
  • 47
  • 54
  • I am having a similar issue. Even though I can see the data in the iCloud folder when I switch my app over to iCloud it doesn't get any results but if I restart the app it does. This is happening on the simulator and I removed LSItemContentTypes – zambono Nov 21 '13 at 01:29
  • @zambono: I would strongly suggest to use real devices and not the simulator when it comes to iCloud. It sounds like your issue is different. My problem was that the folder bundle was not registered correctly, thus the system interpreted (= ignoring) the folder instead of seeing it as file. – auco Nov 21 '13 at 14:47
  • I am still having the issue on device. I have setup LSTypeIsPackage to true, and it sounds counter intuitive to remove the package identifier. I have multiple docs in the app. One works well, the other doesn't. Both are setup the same way. – zambono Dec 03 '13 at 12:09
  • go to https://developer.icloud.com login and navigate to your iCloud folder. If you see your document as file, then you are having a different issue. If you see your document as folder, or (most likely) the contents of your folder as individual files, then you're having the same issue like me. In this case, you need to check the LSItemContentType declaration to make sure that iCloud sees your files as a fileWrapper bundle instead of a folder (thus being ignored by the NSMetadataQuery). – auco Dec 04 '13 at 11:14
  • I see it as a file with the proper extension. By the way I can get the file with the query in simulator, but not on device. I am using iOS 7 and Xcode 5. I can also get the file and its contents if I use the path, its just the query that doesn't return any results. – zambono Dec 04 '13 at 12:40
  • Then you're most likely having another issue that's not related to fileWrappers. Sounds like the iCloud container on your device might be somehow corrupt. Have you tried another device (and/or removing the application from the device, disabling iCloud and restarting and installing it again)? – auco Dec 04 '13 at 14:19
  • Yes I have tried, deleting the app, deleting the files from iCloud, etc. – zambono Dec 04 '13 at 18:44
  • @zambono I am having the exact same issue. Please suggest if you have made it working. – Nabeel Thobani Dec 12 '13 at 06:08
  • @Nabeel I have to do more testing, make sure you have typed in the key names correctly – zambono Feb 26 '14 at 16:42
1

Rather than searching on a file-name predicate, use the UTI-type tree predicate format.

I've used the following to return all files, folders, packages and bundles at a given file URL:

NSMetadataQuery *query = [NSMetadataQuery new];
[query setSearchScopes:@[url]];

NSPredicate *filePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeData];
NSPredicate *bundlePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeBundle];
NSPredicate *packagePredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypePackage];
NSPredicate *folderPredicate = [NSPredicate predicateWithFormat:@"kMDItemContentTypeTree = %@", kUTTypeFolder];

NSPredicate *searchPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[filePredicate, bundlePredicate, packagePredicate, folderPredicate]];

[query setPredicate:searchPredicate];
mrwalker
  • 1,883
  • 21
  • 23