Braintree iOS SDK saying no known class method - ios

I m getting this error. Anyone?
-(void)clientToken{
NSURL *clientTokenURL = [NSURL URLWithString:#"http://tectutiveclients.com/projects/carboss/api/getToken"];
NSMutableURLRequest *clientTokenRequest = [NSMutableURLRequest requestWithURL:clientTokenURL];
[clientTokenRequest setValue:#"text/plain" forHTTPHeaderField:#"Accept"];
[NSURLConnection
sendAsynchronousRequest:clientTokenRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// TODO: Handle errors in [(NSHTTPURLResponse *)response statusCode] and connectionError
clientToken = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// Initialize `Braintree` once per checkout session
[Braintree setupWithClientToken:clientToken
completion:^(Braintree *braintree, NSError *error) {
UIViewController *dropin = [braintree dropInViewControllerWithDelegate:self];
[self presentViewController:[[UINavigationController alloc] initWithRootViewController:dropin]
animated:YES
completion:nil];
// No known class method for selector setupwithClientToken Error
}];
UIViewController *dropin = [self.braintree dropInViewControllerWithDelegate:self];
[self presentViewController:[[UINavigationController alloc] initWithRootViewController:dropin]
animated:YES
completion:nil];
}];
}

I work at Braintree. If you have any more problems, please get in touch with our support team.
This is an inaccuracy in the docs. Instead, please use braintreeWithClientToken:
Example:
NSString *clientToken = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
// Initialize `Braintree` once per checkout session
self.braintree = [Braintree braintreeWithClientToken:clientToken];
Thanks for pointing this out! The docs will be updated shortly.

Related

NSURLConnection method needs to be changed to pass authentication challenge

i have a method for http connection, which was working fine for me until the server i am trying to have an invalid ssl certificate.
Since i am using
[NSURLConnection sendSynchronousRequest:returningResponse:error]
There is no chance to pass authentication challenge by using NSURLConnection delegate methods.
Now, i need to change my service call code as fast as possible.
My method returns the data received from the connection, that is the major problem i can not easily change mine to
NSURLConnection to initWithRequest:delegate:
My service call method is as follows;
-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type
{
globalURL = [[NSURL alloc] initWithString:serviceUrl];
shouldAllowSelfSignedCert = YES;
// if(ISDEBUG) NSLog(#"%#",serviceUrl);
NSMutableDictionary* json;
NSURLResponse* response;
NSData* responseData = [NSMutableData data];
NSError* error = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:globalURL];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: [str dataUsingEncoding: NSUTF8StringEncoding]];
NSString* msgLength = [[NSString alloc] initWithFormat:#"%lu", (unsigned long)[str length]];
[request addValue:#"text/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request addValue:msgLength forHTTPHeaderField:#"Content-Length"];
request.timeoutInterval = 180;
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if([type isEqualToString:#"image"])
{
if(ISDEBUG) NSLog(#"%#",responseData);
return responseData;
}
else
{
if(error)
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NO_WS_CONNECTION message:#"" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
if(ISDEBUG) NSLog(#"%#",error);
}
else
{
if(responseData !=nil)
{
json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:NO_WS_CONNECTION delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if(ISDEBUG) NSLog(#"%#",responseString);
}
return json;
}
I hope i am clear enough.
What is your advise?
Thanks.
You should have a good reason to do it synchronously, so, I will try to help you without changing the flow.
Try wrapping the request into a class where you can implement the request using initWithRequest:delegate: and make the class return the response using block.
You will have something like:
[YourRequestClass requestWithURL:serviceURL callback:^(NSData *yourData, NSError *error){
}];
Ok, at this point you have a new tool that makes ASYNCHRONOUS requests, make the authentication challenge stuff for you and returns the result on a block.
Now, you can simply use dispatch_semaphore to block your thread until the request returns a response ....
-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type {
__block NSData *myData = nil;
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[YourRequestClass requestWithURL:serviceUrl callback:^(NSData *yourData, NSError *error){
//ignoring error (this is an example !)
myData = yourData;
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//Use myData and make yourObject here!
return yourObject;
}
Note that It's just an example, and I'm just trying to pointing you the right way ... I didn't test this code, but I believe it should work as expected!

How to Add Facebook like button to iOS application using Webview?

Right now i am struggling with adding Facebook like button to my App.I referred many sites and even developers.Facebook also not provided proper explanation.They just gave frame for like button. Can any one please help in adding Facebook like button in my App using Webview.
Thanks in Advance
Ok, this is from working project:
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:URL, #"object", nil];
if (FBSession.activeSession.isOpen) {
if (FBSession.activeSession.accessTokenData.accessToken) {
[FBRequestConnection startWithGraphPath:#"/me/og.likes"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { }];
} else NSLog(#"FBSession.activeSession.accessToken IS NULL");
}
URL is the URL of object what you want to like.
There's no code for completionHandler block and for FB-authentification, I hope you can do it as you need.
To get count of Likes for some URL you can use this code:
NSString *likesRequestURL = [[NSString stringWithFormat:#"https://graph.facebook.com/fql?q=SELECT+total_count,+url+FROM+link_stat+WHERE+url+=\"%#\"&access_token=%#", URL, FBSession.activeSession.accessTokenData.accessToken] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:likesRequestURL]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0f];
__block NSString *result = [NSString string];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error == nil) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
SBJsonParser *jsonParser = [[[SBJsonParser alloc] init] autorelease];
result = [NSString stringWithFormat:#"%#", [[[[jsonParser objectWithString:jsonString] objectForKey:#"data"] objectAtIndex:0] objectForKey:#"total_count"]];
[jsonString release];
} else {
NSLog(#"Error = %#", error);
}
}];
Note. In this case was used SBJSONParser, you can use it or replace by something else, just slightly change corresponding code.
Now you can to create fully customized like-button.
It's not right. There is a way to realize Like feature not with UIWebView bit with FBRequestConnection. If you want to use UIWebView - colleague Shan gives right answer, but if you want to use another way - let me to know.

NSURLConnection wrong order

I have a NSURLConnection (two of them), and they're running in the wrong order.
Here's my method:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
}
}
else {
NSLog(#"error: %#", error);
}
}];
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:#"POST"];
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
So, it's two NSURLConnection's that are added to the [NSOperationQueue mainQueue]. What my output is showing me is that the second NSURLConnection is running before the first one. So it tries to go to the page where I download data before I'm logged in, so it (obviously) returns a "You're not logged in" error.
How do I schedule them one after another?
The issue, as I suspect you have realized, is that you're doing asynchronous network requests (which is good; you don't want to block the main queue), so there's no assurance of the order they'll finish.
The quickest and easiest answer is to simply put the call to the second request inside the completion block of the first one, not after it. You don't want to be making that second one unless the first one succeeded anyway.
To keep your code from getting unwieldy, separate the login from the request for main page. And you can use the completion block pattern which is common with asynchronous methods. You add a parameter to loginToMistarWithPin that specifies what it should do when the request finishes. You might have one completion block handler for success, and one for failure:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password success:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
// assuming you validated that everything was successful, call the success block
if (successHandler)
successHandler();
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
if (failureHandler)
failureHandler();
}
}
else {
NSLog(#"error: %#", error);
if (failureHandler)
failureHandler();
}
}];
}
- (void)requestMainPage {
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[requestHome setHTTPMethod:#"GET"]; // this looks like GET request, not POST
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
Then, when you want to login, you can do something like:
[self loginToMistarWithPin:#"1234" password:#"pass" success:^{
[self requestMainPage];
} failure:^{
NSLog(#"login failed");
}];
Now, change those successHandler and failureHandler block parameters to include whatever data you need to pass back, but hopefully it illustrates the idea. Keep your methods short and tight, and use completion block parameters to specify what an asynchronous method should do when it's done.
Can you check the below link. It is about forcing one operation to wait for another.
NSOperation - Forcing an operation to wait others dynamically
Hope this helps.

NSURLConnection taking a long time

This code loads a table view:
- (void)viewDidLoad
{
[super viewDidLoad];
//test data
NSURL *url =[[NSURL alloc] initWithString:urlString];
// NSLog(#"String to request: %#",url);
[ NSURLConnection
sendAsynchronousRequest:[[NSURLRequest alloc]initWithURL:url]
queue:[[NSOperationQueue alloc]init]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if([data length] >0 && connectionError ==nil){
NSArray *arrTitle=[[NSArray alloc]init];
NSString *str=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
arrTitle= [Helper doSplitChar:[Helper splitChar20] :str];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self fecthDataToItem:arrTitle];
[self.tableView reloadData];
NSLog(#"Load data success");
}else if (connectionError!=nil){
NSLog(#"Error: %#",connectionError);
}
}];
// arrTitle = [NSArray arrayWithObjects:#"ee",#"bb",#"dd", nil];
}
And it takes 10 - 15s to load. How can I make this faster?
.
Thanks Rob and rmaddy, problem is solve.
As rmaddy points out, you must do UI updates on the main queue. Failure to do so will, amongst other things, account for some of the problems you're experiencing.
The queue parameter of sendAsynchronousRequest indicates the queue upon which you want the completion block to run. So, you can simply specify [NSOperationQueue mainQueue]:
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if([data length] > 0 && connectionError == nil) {
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *arrTitle = [Helper doSplitChar:[Helper splitChar20] :str];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self fecthDataToItem:arrTitle];
[self.tableView reloadData];
} else if (connectionError!=nil) {
NSLog(#"Error: %#",connectionError);
}
}];
Or, if you where doing something slow or computationally expensive/slow within that block, go ahead and use your own background queue, but then dispatch the UI updates back to the main queue, e.g.:
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// do something computationally expensive here
// when ready to update the UI, dispatch that back to the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// update your UI here
}];
}];
Either way, you should always do UI updates (and probably model updates, too, to keep that synchronized) on the main queue.

best way to implement twitter

1) I have found the Twitter rush sample code from this link Twitter with OAuth
for the integration.
I have added consumer key and secret key. But it never authorizes the app.
2) And if I use share kit it gives the error that there was a problem requesting access from twitter.
3) If I use social framework then it will give alert if user hasn't added his/her account in settings.
I need that user shouldn't go outside the app for twitter login.
Does anyone have any idea on what would be the best way to integrate with twitter?
Please help.
I Hope This will help you . . .
1.Add following classes to your project
GTMOAuthAuthentication.h/m
GTMOAuthSignIn.h/m
GTMHTTPFetcher.h/m
GTMOAuthViewControllerTouch.h/m
GTMOAuthViewTouch.xib
2 . Add following frameworks
Security.framework and SystemConfiguration.framework.
3 .set -ObjC build option for the application target's "Other Linker Flags".
4 . Then it's time for some coding .
import GTMOAuthAuthentication.h and GTMOAuthViewControllerTouch.h
- (void)signInWithTwitter
{
NSURL *requestURL = [NSURL URLWithString:#"https://api.twitter.com/oauth/request_token"];
NSURL *accessURL = [NSURL URLWithString:#"https://api.twitter.com/oauth/access_token"];
NSURL *authorizeURL = [NSURL URLWithString:#"https://api.twitter.com/oauth/authorize"];
NSString *scope = #"http://api.twitter.com/";
GTMOAuthAuthentication *auth = [self authForTwitter];
[auth setCallback:#"http://www.noop.com/OAuthCallback"];
GTMOAuthViewControllerTouch *viewController;
viewController = [[GTMOAuthViewControllerTouch alloc] initWithScope:scope
language:nil
requestTokenURL:requestURL
authorizeTokenURL:authorizeURL
accessTokenURL:accessURL
authentication:auth
appServiceName:#"AppName : Twitter"
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[appDelegate.navigationController pushViewController:viewController animated:YES];
}
- (GTMOAuthAuthentication *)authForTwitter {
GTMOAuthAuthentication *auth = [[GTMOAuthAuthentication alloc] initWithSignatureMethod:kGTMOAuthSignatureMethodHMAC_SHA1
consumerKey:TWITTER_CONSUMER_KEY
privateKey:TWITTER_CONSUMER_SECRET];
[auth setServiceProvider:#"Twitter"];
return auth;
}
- (void)viewController:(GTMOAuthViewControllerTouch *)viewController finishedWithAuth:(GTMOAuthAuthentication *)auth error:(NSError *)error {
if(error)
{
//handle error
}
else
{
// do stuff as per your app.
}
}
NOte : if you get error message like "failed to validate oauth signature and token" then check you system time is correct or not .
If you want that user shouldn't go outside you can use ACAccountStore Account.Framework and Social.framework for iOS 6,
NSUrl *url = [NSURL URLWithString:#"https://api.twitter.com/1.1/users/show.json"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:twittername,#"screen_name",nil];
account = [[ACAccountStore alloc] init];
ACAccountType *twitterAccountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
NSArray *twitterAccounts = [account accountsWithAccountType:twitterAccountType];
// Runing on iOS 6
if (NSClassFromString(#"SLComposeViewController") && [SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
[account requestAccessToAccountsWithType:twitterAccountType options:NULL completion:^(BOOL granted, NSError *error)
{
if (granted)
{
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:url parameters:params];
[request setAccount:[twitterAccounts lastObject]];
dispatch_async(dispatch_get_main_queue(), ^
{
[NSURLConnection sendAsynchronousRequest:request.preparedURLRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response1, NSData *data, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^
{
if (data)
{
// [self loadData:data];
NSString* newStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
NSLog(#"data:%#",newStr);
}
});
}];
});
}
}];
}
else if (NSClassFromString(#"TWTweetComposeViewController") && [TWTweetComposeViewController canSendTweet]) // Runing on iOS 5
{
[account requestAccessToAccountsWithType:twitterAccountType withCompletionHandler:^(BOOL granted, NSError *error)
{
if (granted)
{
TWRequest *request = [[TWRequest alloc] initWithURL:url parameters:params requestMethod:TWRequestMethodGET];
[request setAccount:[twitterAccounts lastObject]];
dispatch_async(dispatch_get_main_queue(), ^
{
[NSURLConnection sendAsynchronousRequest:request.signedURLRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response1, NSData *data, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^
{
if (data)
{
NSString* newStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(#"data:%#",newStr); }
});
}];
});
}
}];
}
}
You have to retain ACAccountStore: in .h
#property (nonatomic, strong) ACAccountStore *account;

Resources