As iOS 9 came by, two bugs appeared in an app that lets it’s users browse the app’s iCloud Drive folder from within the app itself. One related to detecting whether an NSMetadatItem
is a folder or not; the other one related to whether a non-downloaded item was waiting to be downloaded.
Turned out that minor changes in NSMetadataItem
´s attribute keys and values caused these bugs which were easily solved.
Folder Detection
In iOS 8 I used the NSMetadataItemContentTypeKey
key in order to detect whether an NSMetadataItem
was a folder or not:
+ (BOOL)isFolder:(NSMetadataItem*)item
{
NSString *contentType = [item valueForAttribute:NSMetadataItemContentTypeKey];
return contentType ? [contentType isEqualToString:(__bridge NSString *)kUTTypeFolder] : NO;
}
The kUTTypeFolder
constant above corresponds to the UTI string public.folder
.
In iOS 9 this no longer works and the value of NSMetadataItemContentTypeKey
is not public.folder
but rather strange: dyn.ah62d4vv4ge8u
.
Content types for documents such as PDFs and images still return the expected values.
To fix this method in iOS 9 I used the NSMetadataItemContentTypeTreeKey
key instead:
+ (BOOL)isFolder:(NSMetadataItem*)item
{
NSArray *contentTypeTree = [self valueForAttribute:NSMetadataItemContentTypeTreeKey];
APPAssertDebugKindOfClass(contentTypeTree, [NSArray class]);
for (NSString *value in contentTypeTree) {
if ([value isEqualToString:(__bridge NSString *)kUTTypeFolder]) {
return YES;
}
}
}
In both iOS 8 and 9 NSMetadataItemContentTypeTreeKey
returns an array with all UTIs the NSMetadataItem
corresponds to:
kMDItemContentTypeTree = (
"public.folder",
"public.directory",
"public.item"
)
Detect if Download Has Been Requested
For each NSMetadataItem
there is a certain state in which an item has been requested for download but is still waiting for download to start, i.e. the vallue for NSMetadataUbiquitousItemIsDownloadingKey
is NO
. To detect this one can use the NSMetadataUbiquitousItemDownloadRequestedKey
, which returns a NSNumber
-boxed Bool
.
NSMetadataUbiquitousItemDownloadRequestedKey
is not actually in the NSMetadataItem
documentation, but is available in the public header together with the rest of the keys.
On iOS 8 this key is not present in the attribute dictionary so calling valueForAttribute:
on NSMetadataItem
on iOS 8 with this key returns nil
. At least this is the case with iOS 8.4; could be that it was in fact present in earlier versions of iOS 8 (otherwise, why would I have implemented it?).
On iOS 9 however, this key is back and it works as expected. That is, if you expect the value to be YES
even after the download of the NSMetadataItem
has completed.
Tidbit
Also a new interesting key:
BRMetadataItemFileObjectIdentifierKey
This seems to hold an identifier for the NSMetadataItem
, for example 4294989055
.
Searching Google for this key gives voidness, and given the “BR” prefix — let’s leave that one alone.