Using filters in apprequests dialog has no effect - Facebook iOS SDK - facebook-ios-sdk

I'm trying to use the apprequests dialog to send invites to friends who do not have the app installed yet.
To show only the the friends without the app I'm using the filters param with "app_non_users". However it has no affect on the resulting dialog (i get all friends).
This is the code i'm using:
SBJSON *jsonWriter = [[SBJSON new] autorelease];
NSArray *filters = [NSArray arrayWithObject:#"app_non_users"];
NSString *filtersString = [jsonWriter stringWithObject:filters];
NSMutableDictionary* params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"invites you to check out cool stuff", #"message",
#"Check this out", #"notification_text",
filtersString, #"filters",
#"Invite Friends", #"title",
nil];
[facebook dialog:#"apprequests"
andParams:params
andDelegate:self];
What am I missing to get it to work?

"filter" parameter is actually not supported for mobile versions of requests dialogs; see http://developers.facebook.com/docs/reference/dialogs/requests/:
Note: the filters option is disabled on mobile dialogs and will not affect the set of users that appear in the dialog.

It appears this is a Facebook SDK bug:
http://developers.facebook.com/bugs/250244258383454?browse=search_4f612ef5c4d220144914479
Update:
As of 4/19, this was marked "by design".

Related

UIDocumentPickerViewController NewBox App Hangs

I am referring WWDC 2014 sample app NewBox for document provider extension.
I am using following code from NeBox app, to import a document from Document Provider to my app.
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
BOOL startAccessingWorked = [url startAccessingSecurityScopedResource];
NSURL *ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSLog(#"ubiquityURL %#",ubiquityURL);
NSLog(#"start %d",startAccessingWorked);
NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
NSError *error;
[fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
NSData *data = [NSData dataWithContentsOfURL:newURL];
NSLog(#"error %#",error);
NSLog(#"data %#",data);
}];
[url stopAccessingSecurityScopedResource];
}
App totally hangs for coordinateReadingItemAtURL method.
Any inputs will be helpful.
I noticed this problem in NewBox app as well, and decided to trace it. So, there are two extensions in this app: Document Picker and File Provider. To make long story short, there is a race condition between the two when they try to access files within app's document storage folder.
In my opinion, the easiest method to trace down a problem is to put NSLog() in a bunch of locations. The problem is, however, that the debugging output generated by extension won't be visible in Xcode console. The good news is that you can open console in iOS Simulator app by clicking to Debug -> Open System Log menu. This will show all kinds of debugging messages, including those generated by extensions. You can find more about extension debugging here.
By using this method one can easily realize that execution gets stuck in File Provider's startProvidingItemAtURL method. More specifically, the following line causes a deadlock:
[self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
Why is that? Take a look at documentation for coordinateWritingItemAtURL:
If the url parameter specifies a file:
This method waits for other readers and writers of the exact same file to finish in-progress actions.
Function documentPicker that you mentioned calls a read operation, which in its turn triggers a write operation. This is a deadlock. I guess the easiest way to fix it would be to avoid using coordinateWritingItemAtURL in File Provider.
As per documentation:
Each of these methods wait synchronously on the same thread they were invoked on before invoking the passed-in accessor block on the same thread, instead of waiting asynchronously and scheduling invocation of the block on a specific queue.
Apple recommends that you not use file coordination inside this method. The system already guarantees that no other process can access the file while this method is executing. That's the sole reason for this deadlock.
Please refer to this documentation for more details.
You can use block also. Block works too fast, hang problem will get resolve.
Step 1: Take global variable of
UIDocumentPickerViewController *documentPicker;
also decalre
typedef void(^myCompletion)(BOOL);
Step 2: Write a method where allocation takes place and can send callback on completion
-(void) allocateDocumentPicker:(myCompletion) compblock{
//do stuff
documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:#[#"public.content"]
inMode:UIDocumentPickerModeImport];
documentPicker.delegate = self;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
compblock(YES);
}
Step 3: Call the method where allocation is taking place every time you want to open the composer but present it on receiving completion as YES.
-(IBAction)attachmentButtonClicked:(id)sender{
[self allocateDocumentPicker:^(BOOL finished) {
if(finished){
[self.parentScreen presentViewController:documentPicker animated:YES completion:nil];
}
}];
}
Simple Syntax to create own block, take reference from this link
Custom completion block for my own method

GCD network requests failing on iOS 4

I have the following code in my application to load some data from my API. It works fine, great in fact in iOS 5 but on iOS 4 I am getting so many responses with status 204.
This only happens on iOS 4, this could have been treated as an API error, but it works great in the browser, on Rested.app, on iOS 5 etc... only iOS 4 fails, it fails in the simulator and on the device (iPhone 4).
I am calling this code each time I load a cell into a table view. I have a core data object with a load state, set to no initially, if it's not loaded I perform this code, if it's loaded, I skip this code. In the mean time I display a spinner inside the cell on the table view.
I am sure it's a problem with multiple requests in GCD on iOS 4.
Can anyone spot anything wrong with my code snippet?
-(void)myFunction{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// query users participations (Network)
NSError * _urlError = nil;
NSString * url = [NSString stringWithFormat:#"my api url"];
NSMutableURLRequest * loginHTTPRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[loginHTTPRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
NSLog(#"Description: %#", [loginHTTPRequest description]);
NSHTTPURLResponse * _responseHeaders = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:loginHTTPRequest
returningResponse:&_responseHeaders
error:&_urlError];
if(_urlError != nil){
dispatch_async( dispatch_get_main_queue(), ^{
// alert network connection error
});
return;
}
NSString *json_string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary * jsonData = [NSDictionary dictionaryWithDictionary:[parser objectWithString:json_string]];
[json_string release];
[parser release];
dispatch_async( dispatch_get_main_queue(), ^{
// here [_responseHeaders statusCode] keeps returning 204 and there is nothing in responseData
// do some Core Data stuff
});
});
}
UPDATE
Note this code is working fine if called even with a for loop repeatedly, the issue is when I invoke this method from tableView:cellForRowAtIndexPath:
I have Core Data objects with a property "isLoaded" set to NO and changed to YES upon remote load. When my tableview's datasource loads the cells for each object, the tableView:cellForRowAtIndexPath: method calls this function if the object's "isLoaded" property is NO.
I suspected the problem may be because there 2 or more simultaneous calls to the API happening when the table is loaded and reloaded. Each successful load from the api invokes reloadData for that tableview.
This lets me have a pre filled tableview with spinners and asynchronously load in my data as I need it on screen which is nice because I can efficiently use NSFetchedResultsController with lazy loading my objects core data.
(I have an endpoint for all my objects returning an array of object id's - I create Core Data objects with only the ID's, all rest of data, name, date etc etc... is not loaded until it's needed).
When I start scrolling around the new cells which are created/reused call this method and they always get a 200 response with the data. it's only the first loading which causes this "block".
I think I found the problem, I was performing synchronous requests on an asynchronous GCD thread, and for some reason timeouts were occurring, but only on requests in iOS 4, maybe the headers are sent slightly differently from iOS 4 which is causing the API to take longer to respond ? Or maybe multiple (as in simultaneous to the millisecond) requests sent from different threads synchronously on an asynchronous thread were clashing in the system before being sent ?
Anyhow... this didn't seem to be the case calling google.com or even my own private server, so it must be something to do with the headers and multiple requests...
I am using asi http from github and it's working a lot more efficiently, now I am not using GCD for these requests, just an ASI queue.
Any final thoughts on iOS 4 synchronous requests performing on an asynchronous GCD thread with possible timeouts not being respected and returning early with a status 204 ?
Ok - if it is https, then you probably can't get away with using sendSynchronousRequest. The documentation states that things like [NSURLConnection connection:didReceiveAuthenticationChallenge:] won't call some key things, i.e.:
If authentication is required in order to download the request, the required credentials must be specified as part of the URL. If authentication fails, or credentials are missing, the connection will attempt to continue without credentials.
I'm still surprised it's working on iOS5, to be honest. I think you'll have to use asynchronous methods to at least debug it to find out what is going on.

How do you handle a UIManagedDocument?

First off, I should mention that this is my first post on this site. I am trying to teach myself to program iOS and in my google searches for answers I find that I'm constantly directed here. So thank you to all who have contribute here. You have help me a ton already.
I have been going through the Stanford CS193P class and LOVE it. But I'm stuck right now and not sure where to turn.
My problem has been with the UIManagedDocument.
I tired to make a simple app to test my new skills. This is what it does:
A simple accounting app that tracks individual contributions to a fundraising event.
I have a UITabBar that on each tab allows you to:
1. Track the participants (Players) - This will connect to the address book and allow you to add them or just keep them in this app.
2. Manage the events (Events) - You can add, edit or delete events that you will then add participants to and then be able to add what they brought (Bank) in on that event.
3. Settings. - I've added some buttons just to help me figure stuff out now including a reset button that clears all data and a "dummy data" button.
I have three coreData Entities. Players, Events and Bank each with relationships with the other two.
When I first tried to make this app (pre iOS5) I used the appDelegate to create my ManagedObjectContext and pass it around to my viewControllers. That worked. But now I'm supposed to use the UIManagedObjectDocument and not use the AppDelegate. I believe I understand the principle and the integration to iCloud. (I could be wrong)
Using the examples from the class and what I could find online I made a helper class that will provide the first of each of my ViewControllers within my UINavigationControllers the ManagedDocument.
+ (UIManagedDocument *)sharedManagedDocument
{
static UIManagedDocument *sharedDocument = nil;
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"DefaultAppDatabase"];
// url is "<Documents Directory>/<DefaultAppDatabase>"
// Create the shared instance lazily upon the first request.
if (sharedDocument == nil) {
sharedDocument = [[UIManagedDocument alloc] initWithFileURL:url];
}
if (sharedDocument.fileURL != url) {
UIManagedDocument *newDocument = [[UIManagedDocument alloc] initWithFileURL:url];
sharedDocument = newDocument;
}
NSLog(#"SharedDocument: %#", sharedDocument);
return sharedDocument;
}
I then had that first ViewController open the document and perform the fetch.
From there I pass whatever NSManagedObject is selected to the next ViewController through the segue.
The problems are when I get to adding or reseting the data. (I'm assuming that if I can get it to work with the "dummy data" button I can get it to work on an individual entry) When I press the "Reset" or "Dummy" button my logs tell me that it was pushed but I don't see any change in the data until I restart the app. Then it shows up perfectly. My guess is I'm not saving the file correctly or I'm not refreshing the tableViews correctly. I made a small attempt at using NSNotification but didn't go to far into it since I couldn't get it to respond to anything. I'm happy to go back down that road if I need to.
This is my save method... pretty much just copied from the default coreData appDelegate.
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.appDatabase.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
[self.appDatabase saveToURL:self.appDatabase.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success){
if(!success) NSLog(#"failed to save document %#", self.appDatabase.localizedName);
if(success) NSLog(#"Success: save document %#", self.appDatabase.localizedName);
}];
}
Paul, the instructor from CS193P, suggested in Assignment 6 to use a helper method to pass around the UIManagedDocument through a block. I get the theory behind blocks but haven't completely wrapped my head around them so I haven't ruled out that my answer may lie there as well.
Thank you so much for any help or pointing me in the right direction to do more research. Sorry this post is so long, I was trying to be as clear as I can.
I was over thinking the whole thing. Alan asked my question perfectly in this post:
How do I create a global UIManagedDocument instance per document-on-disk shared by my whole application using blocks?
The question and the answers cleared everything up.
Thanks

Trouble in playing video from URL in iPhone using MPMoviePlayerController

I am trying to play a video through a link in my app. The code goes here
NSURL *videoURL = [NSURL URLWithString:viewURL];
NSLog(#"Filepath is: %#", viewURL);
MPMoviePlayerController *movie = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:movie];
movie.view.frame = CGRectMake(0.0f, 50.0f, 320.0f, 320.0f);
movie.fullscreen = YES;
[self.view addSubview:movie.view];
[movie play];
This was written in a method that is called on a button press. This code once worked but now there is no response from the code. Nothing happens when I click on the button even when I connected everything properly in my xib file.
Try this:
Remove
[movie play];
and add
movie.shouldAutoplay = YES;
[movie prepareToPlay];
instead.
Streaming movies (m3u8), from my experience, are a bit quirky when it comes to starting the playback. In certain situations, your original version won't work properly but my replacement always works.
EDIT:
You may also want to check your encodings and delivery using Apples Mediastream Validator as described by this Best Practice Guide and this TechNote.

donloading gif giles in iphone - improving performance

I have a table view showing records
When user taps ona record I need to show the details of that record
The detail shown also includes an image that I need to download from awebserver ( GIF ) file
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
NSData *imageData = [NSData dataWithContentsOfURL:url];
The problem is the last line where it takes some time to download the image
I am wondering what the possible options should be / can be done
I know the initWithRequest is aynchronous - but the call to dataWithContentsofUrl is right in the main path - so user experiences a wait time of more than a second
Is there a way that I could possibly have the dataWithContentsofUrl pushed into some other method that is called asynchronously
If thats possible I could look at showing a spinner or "please wait...." while the image loads
The other option I am thinking of is :
Should I have the images saved on the server in a zipped format ?
and then unzip ?
will it be faster ?
has anyone tried it before ?
or does anyone have a better option ?
I am not looking for spoon feeding but would like to hear your ideas please!

Resources