How to search for uploaded files in iCloud - iphone

I have succeeded uploading a file to iCloud, which can be seen within icloud space manager(but,what odd is the file name is 'unknown').
I also found a piece of code from apple's document
_query = [[NSMetadataQuery alloc] init];
[_query setSearchScopes:[NSArray arrayWithObjects:NSMetadataQueryUbiquitousDataScope, nil]];
[_query setPredicate:[NSPredicate predicateWithFormat:#"%K == '*.*'", NSMetadataItemFSNameKey]];
NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:#selector(fileListReceived)
name:NSMetadataQueryDidFinishGatheringNotification object:nil];
[notificationCenter addObserver:self selector:#selector(fileListReceived)
name:NSMetadataQueryDidUpdateNotification object:nil];
[_query startQuery];
//
[super viewDidLoad];
-(void)fileListReceived
{
NSArray* queryResults = [_query results];
for (NSMetadataItem* result in queryResults) {
NSString* fileName = [result valueForAttribute:NSMetadataItemFSNameKey];
NSLog(#"fileName = %#", fileName);
}
}
but the result is always 0, no matter NSMetadataQueryUbiquitousDataScope or NSMetadataQueryUbiquitousDocumentsScope.
I also know that icloud has backup function, so does backup has any relation with uploading file by app itself?

In your predicate try to use "like" instead of "==".

Related

Update UI after requestAccessToAccountsWithType

I'm developing an app to help me understand OBJECTIVE-X/OSX.
The app simply connects to Facebook and sends a notification using NSUserNotification.
It is working fine, but now I want to add some UI to the mix.
To make the example simpler, I want to update a label (NSTextField) to show the status of the Facebook connection.
Connecting…
Connected
Failed
I have the following code in one File FacebookRequest.m
- (void) connectFacebook{
if(self.account == nil){
self.account = [[ACAccountStore alloc]init];
}
ACAccountType *facebookAccount = [self.account
accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = #{
ACFacebookAppIdKey: #"MY_CODE",
ACFacebookPermissionsKey: #[#"email",
#"user_about_me",
#"user_likes",
#"manage_notifications",
#"user_activities"],
ACFacebookAudienceKey: ACFacebookAudienceFriends
};
[self.account requestAccessToAccountsWithType:facebookAccount
options:options
completion:^(BOOL success, NSError *error){
if(success){
NSArray *accounts = [self.account accountsWithAccountType:facebookAccount];
self.account = [accounts lastObject];
}
else{
NSLog(#"Erro %#", [error description]);
}
}];
}
and the following one in my AppDelegate.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self.statusFacebook setStringValue:#"Connecting…"];
FacebookRequest *request = [[FacebookRequest alloc]init];
[request connectFacebook];
}
What is the best way to update the UI after the request is complete and I have an account?
I'm having troubles since the request is asynchronous and I can't return any value inside the requestAccessToAccountsWithType block. Another point is that if I put some "ifs" to check if my account is nil after it, it will be executed before the block has finished executing, so the account would still be nil.
Thanks!
PS.: Sorry for the English if it is not clear enough.
You may use NSNotificationCenter for this purpose:
[self.account requestAccessToAccountsWithType:facebookAccount
options:options
completion:^(BOOL success, NSError *error){
if(success){
NSArray *accounts = [self.account accountsWithAccountType:facebookAccount];
self.account = [accounts lastObject];
// You post a notification that the UI should update here
[[NSNotificationCenter defaultCenter] postNotificationName:#"UpdateUI" object:nil];
}
else{
NSLog(#"Erro %#", [error description]);
}
}];
Then, you add your viewController that should update its UI as an observer of this notification:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateUI) name:#"UpdateUI" object:nil];
}
- (void)updateUI {
// Here you actually update your UI
}
p.s. if you are not using arc you also remove the observer in dealloc:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];

MPMoviePlayerController ends immediately

I'm trying to load a 25-second mp4 movie from my resource file, but when I play it, my MPMoviePlayerPlaybackDidFinishNotification selector is called immediately with MPMovieFinishReasonPlaybackEnded. When I log my playback state it shows this:
MPMoviePlaybackStatePlaying
MPMoviePlaybackStatePaused
MPMoviePlaybackStateStopped
MovieFinishReasonPlaybackEnded
MPMoviePlaybackStatePlaying
MPMoviePlaybackStatePaused
even though I only call the play method once. I hope someone can help me.
-- Edited to show my code:
MPMoviePlayerController* player = [[[MPMoviePlayerController alloc] initWithContentURL:movieURL] autorelease];
if (player)
{
self.moviePlayerController = player;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:player];
player.contentURL = movieURL;
player.movieSourceType = MPMovieSourceTypeFile;
player.controlStyle = MPMovieControlStyleNone;
player.fullscreen = YES;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
player.view.transform = CGAffineTransformMakeRotation(90.0f * (M_PI / 180.0f));
break;
case UIInterfaceOrientationLandscapeRight:
player.view.transform = CGAffineTransformMakeRotation(-90.0f * (M_PI / 180.0f));
break;
default:
break;
}
player.view.frame = self.view.bounds;
[self.view addSubview:player.view];
}
[self.moviePlayerController play]
Is self.moviePlayerController a retained property? If not, the MPMoviePlayerController instance will be released very quickly (by the autorelease), and you might get similar behaviour.
Without having any more of your code to look at, I would suggest trying to play another file that you know can play. For example, grab the movie from this sample project: http://developer.apple.com/library/ios/#samplecode/MoviePlayer_iPhone/Introduction/Intro.html and see if it plays.
I had something similar happen to me when I was trying to play a file that wasn't properly formatted.
Hmm... I don't see what's wrong. Are you sure that movieURL is correct? How do you get it?
For the record, here is how I present movies, although it wouldn't have quite the same effect as what you're doing.
NSString *path = [[NSBundle mainBundle] pathForResource:movieFileName ofType:#"m4v"];
// If path is NULL (the resource does not exist) return to avoid crash
if (path == NULL)
return;
NSURL *url = [NSURL fileURLWithPath:path];
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
mpViewController.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
mpViewController.moviePlayer.shouldAutoplay = YES;
// NOTE: This can sometimes crash the app in the Simulator. This is a known bug
// in xcode: http://stackoverflow.com/a/8317546/472344
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController release];

CNSetSupportedSSIDs returning false/ not working correctly?

I tried to use CaptiveNetwork in order to replace the web sheet that for user authentication with the network. The method is CNSetSupportedSSIDs.
I tried to add the list, but the web sheet for user authentication still keeps popping up every time I open up my App.
I tried to debug it and I realized that I keep getting the return Value as FALSE.
This is my Code:
-(void)updateSSIDlist
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"ssidInitStarted" object:nil userInfo:nil];
ATT_Remote_Access_Wifi_ClientAppDelegate *delegate = (ATT_Remote_Access_Wifi_ClientAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.ssidInitFinished = NO;
Hotspots *h = [Hotspots defaultHotspots];
NSArray *ssids2 = [h uniqueSSIDs];
NSLog(#"ssids we're shoving down into the system config for iOS to leave alone: %#", [ssids2 description]);
bool ok = CNSetSupportedSSIDs((CFArrayRef) ssids2);
if(ok)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"ssidInitCompleted" object:nil userInfo:nil];
NSLog(#"completed");
}
else
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"ssidInitFailed" object:nil userInfo:nil];
NSLog(#"failed");
}
delegate.ssidInitFinished = YES;
delegate.dbIsBusy = NO;
}
I searched a LOT, but I couldn't find any correct examples or documentation on this.
I also tried the below link example, but even that retuned the same results.
Any help is Appreciated! Thanks!
NSString *values[] = {#"yourssid"};
CFArrayRef arrayRef = CFArrayCreate(kCFAllocatorDefault, (void *)values, (CFIndex)1, &kCFTypeArrayCallBacks);
if( CNSetSupportedSSIDs(arrayRef))
{
NSLog(#"Successfully registered supported network SSIDs");
}
else
{
NSLog(#"Error: Failed to register supported network SSIDs");
}
the login page is blocked but my application will not be called. let's share the experience. thank you

NSMetadataQuery doesn't finish gathering (no notification)

I'm making a backup managrer for my App (via iCloud). I did some tests and the basics worked. But few days later it stopped. I'm using NSMetadataQuery for searching if backup file exists. My backup files are named e.g. Backup29112011154133.xml where numbers represent date of the backup (formatted as ddMMyyyyHHmmss). I check for it in -viewDidAppear:
- (void)viewDidAppear:(BOOL)animated {
[self checkForRemoteFile];
}
- (void)checkForRemoteFile {
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
[query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like 'Backup*'",NSMetadataItemFSNameKey];
[query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query startQuery];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"iCloud is unavailable at the moment" message:nil delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[alert setTag:TAG_ALERT_NOICLOUD];
[alert show];
}
}
- (void)queryDidFinishGathering:(NSNotification *)notif {
NSMetadataQuery *query = [notif object];
[query disableUpdates];
[query stopQuery];
[self loadRemoteFile:query];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
}
- (void)loadRemoteFile:(NSMetadataQuery *)query {
if ([query resultCount] == 1) {
canRestore = YES;
NSMetadataItem *item = [query resultAtIndex:0];
// parse the backup file
[self.tableView reloadData];
} else {
canRestore = NO;
modifDate = #"never";
backupInfoLoaded = YES;
[self.tableView reloadData];
}
}
The problem is that - (void)queryDidFinishGathering:(NSNotification *)notif is never executed. I put breakpints and NSLogs ion there but nothing happend.
I also tried to check for other notifications e.g. 'query did start gathering' and 'query process'. Only 'query did start' notification is posted.
I also have AppID with iCloud registered and entitlements file attached.
Can you help me out what's going on? Maybe I missed something?
First of all NSMetadataQuery doesn't works if startQuery was called not from the MaintThread.
There is possibility that predicate fails for every path also.
Following code works for me.
NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
...
query.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"%%K like \"%#*\"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey];
[query startQuery];
FIXED by creating ivar for NSMetadataQuery.
I don't know why the application can't read data without NSMetadataquery ivar.
Unfortunately there have been many problems with iCloud and using NSMetaDataQuery. To be honest with you the best source as of now for all your iCloud related questions is the Apple Developer Forums. Today Apple released iOS 5.1 beta, and the release notes STILL say that NSMetaDataQuery isn't functioning properly. It's extremely frustrating that iCloud still isn't working properly, but sadly there's nothing we can do.
This problem still persists. I have been able to trace it to the following divergence:
If you limit your search predicate on the query to the name key,
for example
[NSPredicate predicateWithFormat:#"%K like[cd] %#", NSMetadataItemFSNameKey, #"*"]
then it will work as expected (posting all four query lifecycle notifications).
If, however, you try either a compound predicate or try to work with the path,
as in
[NSPredicate predicateWithFormat:#"%K BEGINSWITH %#", NSMetadataItemPathKey, [self cloudDocumentsURL].path]
OR
[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:namePred, pathPred, nil]];
Then only the initial notification will be posted.
I have tried literally hundreds of combinations of these configurable variables in multiple test and intended-for-production apps over the last year and have yet to find a counterexample to this hypothesis.
Unfortunately, NSMetadataQuery just doesn't work for ubiquitous stores (as of 10.8).
My workaround is to get the raw results from the query and work mostly on a bound NSArrayController which can have its results filtered. This will mean refactoring away from query.results for most existing code and there is a performance hit (presumably) but it is the only way I have found. I would love an alternative.

iCloud: How to read in directories created by the user

I would like to read in a list of all directories that are created either by the user or the app in iCloud's Mobile Documents directory (the one found in Lion under ~/Library/Mobile Documents). Here is an example of how this directory could look like:
I tried the following code, but the query I run will not contain any objects representing my folders (using the NSPredicate predicateWithFormat:#"%K.pathExtension = ''", NSMetadataItemFSNameKey). If I run a query for txt files (using #"%K ENDSWITH '.txt'", NSMetadataItemFSNameKey), I will get 5 objects returned for the txt files respectively. Looking for txt files thus works, but not for directories. Reading through the docs, I noticed that Apple suggests to use NSFileWrapper (File Packages) instead of directories. Is iCloud not able to handle/detect directories created by the user or the app?
Here is my code:
-(void)loadDocument {
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
_query = query;
//Search all files in the Documents directories of the application’s iCloud container directories:
[query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K.pathExtension = ''", NSMetadataItemFSNameKey];
[query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query startQuery];
}
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates]; // You should invoke this method before iterating over query results that could change due to live updates.
[query stopQuery]; // You would call this function to stop a query that is generating too many results to be useful but still want to access the available results.
[self loadData:query];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
_query = nil; // we're done with it
}
- (void)loadData:(NSMetadataQuery *)query {
NSLog(#"Query count %i", [query resultCount]);
for (int i=0; i < [query resultCount]; i++) {
NSMetadataItem *item = [query resultAtIndex:i];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
NSLog(#"%i.URL: %#", i, url);
}
}
I had a look at "Manage Storage" in the iClouds Settings in Mac OS X Lion. When I click my application, it will only show the different txt files (plus conflicting versions) and no directories whatsoever. So I have to assume that you can only work with wrappers / file packages but not with directories.