How to get user details using twitter api v1.1 (Twitter error 215) - iphone

I have used the twitter api provided by twitter,to get the details but
not able to execute it, even tried to pass the authentication data
like consumer secret key, consumer key, token but the result is same.
I am able to login and receiving twitter authentication token but not able to get user details.
Below code is used by me (I am using MGtwitter engine) :
NSMutableURLRequest *request =[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1.1/users/show.json?screen_name=%#",username]]];
NSData *returnData = [ NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil ];
NSString *returnString = [[NSString alloc]initWithData:returnData encoding:NSUTF8StringEncoding];
NSError *err = nil;
twitterLogin = [NSJSONSerialization JSONObjectWithData:[returnString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err];
Error is shown as below:
errors = (
{
code = 215;
message = "Bad Authentication data";
} );

First, you need to Authenticate your request (Get permission).
second, see follow these steps:
1.Download FHSTwitterEngine Twitter Library.
2.Add the folder FHSTwitterEngine" to your project and #import "FHSTwitterEngine.h".
3.add SystemConfiguration.framework to your project.
Usage : 1.in the [ViewDidLoad] add the following code.
UIButton *logIn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
logIn.frame = CGRectMake(100, 100, 100, 100);
[logIn setTitle:#"Login" forState:UIControlStateNormal];
[logIn addTarget:self action:#selector(showLoginWindow:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:logIn];
[[FHSTwitterEngine sharedEngine]permanentlySetConsumerKey:#"<consumer_key>" andSecret:#"<consumer_secret>"];
[[FHSTwitterEngine sharedEngine]setDelegate:self];
and don't forget to import the delegate FHSTwitterEngineAccessTokenDelegate.
you need to get the permission for your request, with the following method which will present Login window:
- (void)showLoginWindow:(id)sender {
[[FHSTwitterEngine sharedEngine]showOAuthLoginControllerFromViewController:self withCompletion:^(BOOL success) {
NSLog(success?#"L0L success":#"O noes!!! Loggen faylur!!!");
}];
}
when the Login window is presented, enter your Twitter Username and Password to authenticate your request.
add the following methods to your code:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[FHSTwitterEngine sharedEngine]loadAccessToken];
NSString *username = [[FHSTwitterEngine sharedEngine]loggedInUsername];// self.engine.loggedInUsername;
if (username.length > 0) {
lbl.text = [NSString stringWithFormat:#"Logged in as %#",username];
[self listResults];
} else {
lbl.text = #"You are not logged in.";
}
}
- (void)storeAccessToken:(NSString *)accessToken {
[[NSUserDefaults standardUserDefaults]setObject:accessToken forKey:#"SavedAccessHTTPBody"];
}
- (NSString *)loadAccessToken {
return [[NSUserDefaults standardUserDefaults]objectForKey:#"SavedAccessHTTPBody"];
}
4.Now you are ready to get your request, with the following method(in this method I created a Twitter search for some Hashtag, to get the screen_name for example):
- (void)listResults {
dispatch_async(GCDBackgroundThread, ^{
#autoreleasepool {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// the following line contains a FHSTwitterEngine method wich do the search.
dict = [[FHSTwitterEngine sharedEngine]searchTweetsWithQuery:#"#iOS" count:100 resultType:FHSTwitterEngineResultTypeRecent unil:nil sinceID:nil maxID:nil];
// NSLog(#"%#",dict);
NSArray *results = [dict objectForKey:#"statuses"];
// NSLog(#"array text = %#",results);
for (NSDictionary *item in results) {
NSLog(#"text == %#",[item objectForKey:#"text"]);
NSLog(#"name == %#",[[item objectForKey:#"user"]objectForKey:#"name"]);
NSLog(#"screen name == %#",[[item objectForKey:#"user"]objectForKey:#"screen_name"]);
NSLog(#"pic == %#",[[item objectForKey:#"user"]objectForKey:#"profile_image_url_https"]);
}
dispatch_sync(GCDMainThread, ^{
#autoreleasepool {
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Complete!" message:#"Your list of followers has been fetched" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
});
}
});
}
That's all.
I just got the screen_name from a search Query, you can get a timeline for a user using the following methods:
// statuses/user_timeline
- (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count;
- (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID;
instead of the search method above.
Note: see the FHSTwitterEngine.h to know what method you need to use.
Note: to get the <consumer_key> and the <consumer_secret> you need to to visit this link
to register your app in Twitter.

Got the solution after MKAlatrash revert, to get the user profile follow certain steps in the code as under :
[[FHSTwitterEngine sharedEngine]getProfileImageForUsername:username andSize:FHSTwitterEngineImageSizeNormal];
jump to definition of this function and replace the if ... else if part
if ([userShowReturn isKindOfClass:[NSError class]]) {
return [NSError errorWithDomain:[(NSError *)userShowReturn domain] code:[(NSError *)userShowReturn code] userInfo:[NSDictionary dictionaryWithObject:request forKey:#"request"]];
NSLog(#"user show return %#",userShowReturn);
} else if ([userShowReturn isKindOfClass:[NSDictionary class]]) {
return userShowReturn;
NSString *url = [userShowReturn objectForKey:#"profile_image_url"]; // normal
if (size == 0) { // mini
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#"_mini"];
} else if (size == 2) { // bigger
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#"_bigger"];
} else if (size == 3) { // original
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#""];
}
id ret = [self sendRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
if ([ret isKindOfClass:[NSData class]]) {
return [UIImage imageWithData:(NSData *)ret];
}
return ret;
}
That really was helpful thanks

Related

Listing All Folder content from Google Drive

Hi I have integrated google Dive with my app using Dr. Edit sample code from google drive. But i am not able to view all the files, which are stored in my Google Drive account.
// I have tried this
-(void)getFileListFromSpecifiedParentFolder
{
GTLQueryDrive *query2 = [GTLQueryDrive queryForChildrenListWithFolderId:#"root"];
query2.maxResults = 1000;
[self.driveService executeQuery:query2
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveChildList *children, NSError *error)
{
NSLog(#"\nGoogle Drive: file count in the folder: %d", children.items.count);
if (!children.items.count)
{
return ;
}
if (error == nil)
{
for (GTLDriveChildReference *child in children)
{
GTLQuery *query = [GTLQueryDrive queryForFilesGetWithFileId:child.identifier];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *file,
NSError *error)
{
NSLog(#"\nfile name = %#", file.originalFilename);}];
}
}
}];
}
//I want to Display All content in NSLog...
1. How to get all files from Google Drive.
First in viewDidLoad: method check for authentication
-(void)viewDidLoad
{
[self checkForAuthorization];
}
And here is the definition of all methods:
// This method will check the user authentication
// If he is not logged in then it will go in else condition and will present a login viewController
-(void)checkForAuthorization
{
// Check for authorization.
GTMOAuth2Authentication *auth =
[GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientId
clientSecret:kClientSecret];
if ([auth canAuthorize])
{
[self isAuthorizedWithAuthentication:auth];
}
else
{
SEL finishedSelector = #selector(viewController:finishedWithAuth:error:);
GTMOAuth2ViewControllerTouch *authViewController =
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientId
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:finishedSelector];
[self presentViewController:authViewController animated:YES completion:nil];
}
}
// This method will be call after logged in
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth: (GTMOAuth2Authentication *)auth error:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:nil];
if (error == nil)
{
[self isAuthorizedWithAuthentication:auth];
}
}
// If everthing is fine then initialize driveServices with auth
- (void)isAuthorizedWithAuthentication:(GTMOAuth2Authentication *)auth
{
[[self driveService] setAuthorizer:auth];
// and finally here you can load all files
[self loadDriveFiles];
}
- (GTLServiceDrive *)driveService
{
static GTLServiceDrive *service = nil;
if (!service)
{
service = [[GTLServiceDrive alloc] init];
// Have the service object set tickets to fetch consecutive pages
// of the feed so we do not need to manually fetch them.
service.shouldFetchNextPages = YES;
// Have the service object set tickets to retry temporary error conditions
// automatically.
service.retryEnabled = YES;
}
return service;
}
// Method for loading all files from Google Drive
-(void)loadDriveFiles
{
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.q = [NSString stringWithFormat:#"'%#' IN parents", #"root"];
// root is for root folder replace it with folder identifier in case to fetch any specific folder
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *files,
NSError *error) {
if (error == nil)
{
driveFiles = [[NSMutableArray alloc] init];
[driveFiles addObjectsFromArray:files.items];
// Now you have all files of root folder
for (GTLDriveFile *file in driveFiles)
NSLog(#"File is %#", file.title);
}
else
{
NSLog(#"An error occurred: %#", error);
}
}];
}
Note: For get full drive access your scope should be kGTLAuthScopeDrive.
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientId
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:finishedSelector];
2. How to download a specific file.
So for this you will have to use GTMHTTPFetcher. First get the download URL for that file.
NSString *downloadedString = file.downloadUrl; // file is GTLDriveFile
GTMHTTPFetcher *fetcher = [self.driveService.fetcherService fetcherWithURLString:downloadedString];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error)
{
if (error == nil)
{
if(data != nil){
// You have successfully downloaded the file write it with its name
// NSString *name = file.title;
}
}
else
{
NSLog(#"Error - %#", error.description)
}
}];
Note: If you found "downloadedString" null Or empty just have look at file.JSON there are array of "exportsLinks" then you can get the file with one of them.
3. How to upload a file in specific folder: This is an example of uploading image.
-(void)uploadImage:(UIImage *)image
{
// We need data to upload it so convert it into data
// If you are getting your file from any path then use "dataWithContentsOfFile:" method
NSData *data = UIImagePNGRepresentation(image);
// define the mimeType
NSString *mimeType = #"image/png";
// This is just because of unique name you can give it whatever you want
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MMM-yyyy-hh-mm-ss"];
NSString *fileName = [df stringFromDate:[NSDate date]];
fileName = [fileName stringByAppendingPathExtension:#"png"];
// Initialize newFile like this
GTLDriveFile *newFile = [[GTLDriveFile alloc] init];
newFile.mimeType = mimeType;
newFile.originalFilename = fileName;
newFile.title = fileName;
// Query and UploadParameters
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:mimeType];
GTLQueryDrive *query = [GTLQueryDrive queryForFilesInsertWithObject:newFile uploadParameters:uploadParameters];
// This is for uploading into specific folder, I set it "root" for root folder.
// You can give any "folderIdentifier" to upload in that folder
GTLDriveParentReference *parentReference = [GTLDriveParentReference object];
parentReference.identifier = #"root";
newFile.parents = #[parentReference];
// And at last this is the method to upload the file
[[self driveService] executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error){
NSLog(#"Error: %#", error.description);
}
else{
NSLog(#"File has been uploaded successfully in root folder.");
}
}];
}

GData Objective-C Client Contact Service

I downloaded the last GData client via SVN https://code.google.com/p/gdata-objectivec-client/
I succesfully compiled it and I integrated successfully the static library inside my project.
I need to retrieve all gmail contacts about a google username:
- (GDataServiceGoogleContact *)contactService {
static GDataServiceGoogleContact* service = nil;
if (!service) {
service = [[GDataServiceGoogleContact alloc] init];
[service setShouldCacheResponseData:YES];
[service setServiceShouldFollowNextLinks:YES];
}
// update the username/password each time the service is requested
NSString *username = usr.text;
NSString *password = psw.text;
[service setUserCredentialsWithUsername:username
password:password];
return service;
}
- (IBAction)getContacts:(id)sender; {
GDataServiceGoogleContact *gc =[self contactService];
NSURL *feedURL = [GDataServiceGoogleContact contactFeedURLForUserID:usr.text];
GDataServiceTicket *ticket;
ticket = [gc fetchFeedWithURL:feedURL
delegate:self
didFinishSelector:#selector(ticket:finishedWithFeed:error:)];
[self startLoading];
}
The callback selector looks like this:
- (void)ticket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataFeedContact *)feed
error:(NSError *)error {
[self stopLoading];
if (error == nil) {
NSArray *entries = [NSArray arrayWithArray:[feed entries]];
if ([entries count] > 0) {
for (GDataEntryContact *firstContact in entries) {
NSString *name = [((GDataNameElement*)[[firstContact name] fullName]) stringValue];
NSString *email = ([firstContact emailAddresses] != nil && [[firstContact emailAddresses] count]!=0) ? [[[firstContact emailAddresses] objectAtIndex:0] stringValueForAttribute:#"address"]: NSLocalizedString(#"not found",#"");
if (name == nil) {
name = email;
}
BBGmailContact *tmpContact = [[BBGmailContact alloc] initWithName:name email:email];
[contacts addObject:tmpContact];
[self.navigationController popViewControllerAnimated:YES];
}
[gmailDelegate contactsDidDownload:contacts];
} else {
[self createAlertView:NSLocalizedString(#"Warning", #"") message:NSLocalizedString(#"No contact found", #"")];
}
} else {
[self createAlertView:NSLocalizedString(#"Error", #"Error") message:NSLocalizedString(#"Please, check your user and password", #"")];
}
}
Why is every entry of entries a kind of class: GDataEntryBase instead GDataEntryContact?
Where is my error? Can someone help me?
Entries are created as GDataEntryBase if the application does not have the service-specific classes for Contacts compiled and linked into the app.
Be sure too that the appropriate build flags for the Contacts service are specified as described in the docs.

Using the YouTube API and iPhone SDK, how would I get information about a search result?

I'm trying to simply search for videos using a query, which is working perfectly using the below code.
// Create a service object for executing queries
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Services which do not require sign-in may need an API key from the
// API Console
service.APIKey = #"AIzaSy...";
// Create a query
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = searchBar.text;
query.videoEmbeddable = #"true";
query.type = #"video";
//query.country = #"US";
// Execute the query
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil) {
GTLYouTubeSearchListResponse *products = object;
[videoArray removeAllObjects];
// iteration of items and subscript access to items.
for (GTLYouTubeSearchResult *item in products) {
NSMutableDictionary *dictionary = [item JSONValueForKey:#"id"];
NSLog(#"%#", [dictionary objectForKey:#"videoId"]);
YoutubeVideo *video = [[YoutubeVideo alloc]init];
[video setLblTitle:item.snippet.title];
//Get youtube video image
[video setImgIconURL:[NSURL URLWithString:item.snippet.thumbnails.defaultProperty.url]];
[video setLblVideoURL:[dictionary objectForKey:#"videoId"]];
[video setLblChannelTitle:item.snippet.channelTitle];
[videoArray addObject:video];
}
reloadData = YES;
[tableView reloadData];
//Download images asynchronously
[NSThread detachNewThreadSelector:#selector(downloadImages)
toTarget:self
withObject:nil];
}else{
NSLog(#"Error: %#", error.description);
}
}];
However, now I'd like to display certain information about the video. Some of this information I can get out of
item.snippet
But I also need to get the video duration, and number of views. How can I get them using Youtube API 3.0?? I also had an idea to try using GData just for this, but it literally triples the load time to use
NSString *JSONString = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://gdata.youtube.com/feeds/api/videos/%#?v=2&alt=json", [video lblVideoURL]]] encoding:NSUTF8StringEncoding error:nil ];
How do I get the duration of the video, plus the number of views the video has?
Search query only accept ID and Snippet as parts. If you change to Video List Query you can include other parts, but you have to use one of the filters.
I think you'll have to get the video ID with the search query and do another query (Now a video query) filtering by ID (the Id you got), than you can get all other information of the videos you searched.
The problem is i'm having trouble getting the video ID, i think the API use the word "identifier" instead of "id" because it's a reserved word of objective-c.
Edit: Yeah, it was just a matter of time, just request my GTLYoutubeSearchResponse.JSON, an manipulated it as i wanted.
FIRST QUERY:
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = #"iphone";
query.fields = #"items(id,snippet)";
query.order = #"viewCount";
//query.channelId = #"UCsnbNwitAF9BzjjdMfRyK2g";//Kavaco
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
appDelegate.videos = object;
[self performSegueWithIdentifier:#"videoList" sender:self];
}
else {
NSLog(#"%#", error.description);
}
}];
SECOND QUERY: In my TableViewController, inside my cellForRowAtIndexPath i do another query for each video i found. Be sure to request only the variables you need to avoid spending your credits, in my case i requested only viewCount.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCell" forIndexPath:indexPath];
GTLYouTubeVideo *video = appDelegate.videos[indexPath.row];
NSMutableDictionary *videoIdJson = [video.JSON objectForKey:#"id"];
NSString *videoId = [videoIdJson objectForKey:#"videoId"];
cell.textLabel.text = video.snippet.title;
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithPart:#"statistics"];
query.identifier = videoId;
query.maxResults = 1;
query.fields = #"items/statistics(viewCount)";
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
GTLYouTubeVideoListResponse *detalhe = object;
NSMutableDictionary *responseJSON = detalhe.JSON;
NSArray *tempArray = [responseJSON objectForKey:#"items"];
NSMutableDictionary *items = tempArray[0];
NSMutableDictionary *statistics = [items objectForKey:#"statistics"];
_views = [[NSString alloc] initWithFormat:#"Views: %#",[statistics objectForKey:#"viewCount"]];
cell.detailTextLabel.text = _views;
}
else {
NSLog(#"%#", error.description);
}
}];
cell.detailTextLabel.text = _views;
return cell;
}
Hope it helps.
Collect the id from search API and do another video list API call is the proper way to do what you want to achieve. The video list API call can put multiple video ids separate by comma in the same call. The extra call shouldn't consider exhausting because this is expected behavior on API v3:
Project Member #1 je...#google.com
That's the expected behavior, and not likely to change. Since the
search.list() method can return channels, videos, and playlists, only
properties that make sense for all of those resource types are
returned in the search responses. If you need to obtain any other
properties, making a follow-up request to, e.g., videos.list() is
required. Note that you can pass in up to 50 video ids to
videos.list(), so you can effectively look up an entire page's worth
of search.list() results in a single video.list() call.
If you try https://developers.google.com/youtube/v3/docs/videos/list#try-it , you set contentDetails,statistics as the part, you should able to get the following result:
"contentDetails": {
"duration": "PT20M38S",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": false
},
"statistics": {
"viewCount": "191",
"likeCount": "7",
"dislikeCount": "0",
"favoriteCount": "0",
"commentCount": "0"
}
PT20M38S means 20 minutes and 38 seconds, based on ISO 8601(http://en.wikipedia.org/wiki/ISO_8601)
The best way for make this is:
if (!service) {
service = [[GTLServiceYouTube alloc] init];
service.shouldFetchNextPages = YES;
service.shouldFetchInBackground = YES;
service.retryEnabled = YES;
service.APIKey = #"AIzaSyDSO2JPnM_r9VcDrDJJs_d_7Li2Ttk2AuU";
}
[youtubeList removeAllObjects];
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id"];
query.maxResults = 50;
query.q = withText;
query.fields = #"items(id)";
query.order = #"viewCount";
query.type = #"video";
// query.videoDuration = #"long";//any-long-medium-short
__block NSInteger incrementRequest = 0;
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *idsResponse = object;
for (GTLYouTubeVideoListResponse *videoInfo in object) {
[youtubeList addObject:videoInfo.JSON];
GTLQueryYouTube *query2 = [GTLQueryYouTube queryForVideosListWithIdentifier:[[videoInfo.JSON valueForKey:#"id"] valueForKey:#"videoId"] part:#"id,contentDetails,snippet,statistics"];
query2.maxResults = 1;
query2.fields = #"items(id,contentDetails,snippet,statistics)";
query2.order = #"viewCount";
[service executeQuery:query2 completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *detalhe = object;
for (NSMutableDictionary *tmpDict in youtubeList) {
if ([[[tmpDict valueForKey:#"id"] valueForKey:#"videoId"] isEqualToString:[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"id"]]) {
[tmpDict removeObjectForKey:#"id"];
//condition personal
if (![Utils parseISO8601TimeIsGrater30:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"duration"]]) {
BOOL isBlockedInUs = NO;
for (NSString *countryRestric in [[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"regionRestriction"] valueForKey:#"blocked"]) {
if ([countryRestric isEqualToString:#"US"]) {
isBlockedInUs = YES;
break;
}
}
if (!isBlockedInUs) {
[tmpDict addEntriesFromDictionary:detalhe.JSON];
[tmpDict setValue:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"snippet"] valueForKey:#"publishedAt"] forKey:#"publishedAt"];
} else {
[youtubeList removeObject:tmpDict];
}
} else {
[youtubeList removeObject:tmpDict];
}
break;
}
}
incrementRequest ++;
if ([idsResponse.items count] == incrementRequest) {
//Finish
[self.tableView reloadData];
}
}];
}
}];

Strange RestKit / RKRequestQueue synchronous Issue

I have an ARC-enabled project using RestKit and although most of my requests are done asynchronously, I am having an issue with performing a synchronous request:
In my AppDelegate:
else if (![IKUserController loggedInUserIsAuthenticated]) {
IKLoginViewController *loginVC = [[IKLoginViewController alloc] init];
loginVC.scenario = SCENARIO_EXISTING;
[self.window.rootViewController presentModalViewController:loginVC animated:YES];
}
In the implementation for loggedInUserIsAuthenticated:
+ (BOOL)loggedInUserIsAuthenticated {
IKUser *user = [IKUserController loggedInUser];
if (!user) {
return NO;
}
else {
NSString *username = user.userName;
NSString *password = user.userPassword;
if ([IKUserController loginWithUsername:username password:password]) {
return YES;
}
else {
return NO;
}
}
return NO;
}
and the loginWithUserName:password:
+ (BOOL)loginWithUsername:(NSString *)username password:(NSString *)password {
//return YES;
NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:username, #"username", password, #"password", nil];
RKResponse *response = [[[RKClient sharedClient] post:#"/user/authenticate" params:params delegate:nil] sendSynchronously];
if (response.isOK) {
return YES;
}
else {
return NO;
}
return NO;
}
and the error:
*** Assertion failure in -[RKRequestQueue removeRequest:decrementCounter:], /Users/admin/Documents/dev/RestKit/Code/Network/RKRequestQueue.m:350
The RKClient method post already adds the request to the default request queue, so I think the problem is that you send the request twice - once async and once sync. Instead of using RKClient post method, configure the request manually. There is a method setupRequest on RKClient, this will make it easier for you and you will only need to define the url, method and params, like this:
RKRequest* req = [RKRequest requestWithURL:reqURL delegate:self];
[req setMethod:RKRequestMethodPOST];
[req setParams:params];
[client setupRequest:req];
[req sendSynchronously];

Facebook-iOs-API How to get response in custom function

How to catch response in custom function? Basically answer gets:
- (void)request:(FBRequest *) request didReceiveResponse:(NSURLResponse *)response{
NSLog(#"I have some information");
// [wait stopAnimating];
//wait.hidden;
}
- (void)request:(FBRequest *) request didLoad:(id)result{
if ([result isKindOfClass:[NSArray class]]){
result = [result objectAtIndex:0];
}
else{
// dictionaryWithNames = result;
infoStatus.text = [result objectForKey:#"name"];
infiId.text = [result objectForKey:#"id"];
}
if ([result objectForKey:#"data"]){
arrayWithFriends = [result objectForKey:#"data"];
if (arrayWithFriends != nil) {
for (NSDictionary *output in arrayWithFriends){
NSString *namaFriends = [output objectForKey:#"name"];
NSLog(#"Your Friend %#", namaFriends);
infoStatus.text = #"If you could see konsole... You can't";
continue;
}
} else {
infoStatus.text = #"You Haven't Got friends or Mutuals";
}
}
}
But i need to have another function because its impossible(or too hard) to get all responses that i need, using only few patterns in this function.
you can use same schema as facebook developers in their sample application here
https://github.com/facebook/wishlist-mobile-sample/blob/master/iOS/Wishlist/Wishlist/HomeViewController.m
they create currentAPIcall variable and fill it depending on request like that:
/**
* Make a Graph API Call to get information about the current logged in user.
*/
- (void) apiFQLIMe {
currentAPICall = kAPIFQLMe;
// Using the "pic" picture since this currently has a maximum width of 100 pixels
// and since the minimum profile picture size is 180 pixels wide we should be able
// to get a 100 pixel wide version of the profile picture
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"SELECT uid, name, pic FROM user WHERE uid=me()", #"query",
nil];
[facebook requestWithMethodName:#"fql.query"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
[self hideActivityIndicator];
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
switch (currentAPICall) {
case kAPIFQLMe:
{
// This callback can be a result of getting the user's basic
// information or getting the user's permissions.
if ([result objectForKey:#"name"]) {
// If basic information callback, set the UI objects to
// display this.
self.profileNameLabel.text = [result objectForKey:#"name"];
// Get the pr
...