I'm pretty new to RubyMotion and I've just hit a wall.
I'm trying to do some LinkedIn oauth work and I need to convert the following to RubyMotion
client = LIALinkedInHttpClient.clientForApplication(application, presentingViewController:nil)
client getAuthorizationCode:^(NSString * code) {
[self.client getAccessToken:code success:^(NSDictionary *accessTokenData) {
NSString *accessToken = [accessTokenData objectForKey:#"access_token"];
[self.client getPath:[NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~?oauth2_access_token=%#&format=json", accessToken] parameters:nil success:^(AFHTTPRequestOperation * operation, NSDictionary *result) {
NSLog(#"current user %#", result);
} failure:^(AFHTTPRequestOperation * operation, NSError *error) {
NSLog(#"failed to fetch current user %#", error);
}];
} failure:^(NSError *error) {
NSLog(#"Quering accessToken failed %#", error);
}];
} cancel:^{
NSLog(#"Authorization was cancelled by user");
} failure:^(NSError *error) {
NSLog(#"Authorization failed %#", error);
}];
Could anyone possibly point me in the write direction?
The less-typing way using Ruby 2.0's stabby lambdas looks like this:
client.getAuthorizationCode -> (code) {
NSLog "Success"
}, cancel: ->
NSLog "Auth was cancelled"
}, failure: -> (error) {
NSLog "Auth failed"
}
Here's an idea of how you'd use Objective-C blocks in RubyMotion:
client.getAuthorizationCode(lambda { |code|
}, cancel: lambda {
}, failure: lambda { |error|
})
I believe you can use the lambda shorthand -> or Proc if you prefer. See the RubyMotion docs for more info. They demonstrate using do and end to begin and finish the block, but for this purpose, I prefer braces.
Related
Situation
I am trying to change an Objective-C project from Parse to firebase. What I am trying to do is replacing Parse codes with corresponding firebase code. This strategy worked for my login page and login was successful
The login page calls a segue to MainViewController. The MainViewController loads but the app crashes with an error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot do a comparison query for type: (null)'
What I Did
This is the firebase code I added in LoginViewController - (IBAction)loginButtonClicked:(id)sender
//Checking for username and password
_emailId=_emailTextField.text;
_password=_passwordTextField.text;
//reference for firebase
self.ref = [[FIRDatabase database] reference];
if([self isInternet])
{
//firebase authentication
[[FIRAuth auth]signInWithEmail:_emailId password:_password completion:^(FIRUser *user, NSError *error) {
// ...
if (error) {
//login failed
[self failsLoginWithError:#"Please try again later"];
}
else
{
NSLog(#"Login Successful");
[self successLoginWithResposne:user];
}
and this is the parse code I commented out
PFQuery *query=[PFQuery queryWithClassName:#"normal"];
[query whereKey:#"usermail" equalTo:_emailId];
[query whereKey:#"password" equalTo:_password];
[query whereKey:#"user_removed" equalTo:#(0)];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
//login failed
[self failsLoginWithError:#"Please try again later"];
}
if ([objects count]==0) {
NSLog(#"Invalid username or passowrd");
[self failsLoginWithError:#"Invalid email or password"];
} else {
PFObject *obj = [objects firstObject];
ud = [NSUserDefaults standardUserDefaults];
BOOL isBlocked = [[obj valueForKey:#"blocked"] boolValue];
BOOL isLogged = [[obj valueForKey:#"logged"]boolValue];
NSString *userID = [ud objectForKey:#"ObjectID"];
if (isLogged) {
if ([userID isEqualToString:obj.objectId]) {
if (isBlocked) {
[self failsLoginWithError:#"Login Blocked! Please contact your Doctor"];
}else{
// Login success
[self successLoginWithResposne:obj];
}
}
else{
// login Failed
[obj setValue:#(1) forKey:#"blocked"];
[obj saveInBackground];
[self failsLoginWithError:#"Login Blocked! Please contact your Doctor"];
}
}
else {
// login success
[obj setValue:#(1) forKey:#"logged"];
[obj saveInBackground];
[self successLoginWithResposne:obj];
}
}
} ];
The error message says "exception due to comparison with a null value".
Guess this is due to some parse code somewhere comparing a value that is received from the LoginViewController (which I commented out).
Question
How to fix this?
How do I find the part where the comparison is happening?
Do I have to replace every parse code with firebase code before executing?
if so, How to find every parse code in the project?
Crash report:
Exact line where code crashes:
You may look for the User system parse has build in
Example
[PFUser logInWithUsernameInBackground:_emailId password:_password
block:^(PFUser *user, NSError *error) {
if (user) {
if(user[#"blocked"] == #YES){
return [PFUser logOut];
}else{
// USER AUTHENTICATED
}
} else {
// Password, Conection
}
}];
All local store will be available by using this anywhare in your app:
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
// do stuff with the user
} else {
// show the signup or login screen
}
If you want to auth with the email insted of a "username" just use the username as the email in registration.
so created a simple application to test out sendbird services, they look best, so i have read their documentation, and at this moment. i made something.. and i got a problem there, when do i have to call the didReceiveMessage or why mine is not working?
myCode
- (IBAction)connnect:(id)sender {
[SBDOpenChannel getChannelWithUrl:#"iDict" completionHandler:^(SBDOpenChannel * _Nullable channel, SBDError * _Nullable error) {
if (error != nil) {
NSLog(#"Error 1 : %#", error.localizedDescription);
return;
}
[channel enterChannelWithCompletionHandler:^(SBDError * _Nullable error) {
if (error != nil) {
NSLog(#"Error: %#", error);
return;
}
NSLog(#"Connected to Channel : %#",channel.channelUrl);
// ...
}];
}];
}
- (IBAction)sendMessage:(id)sender {
[self.channel sendUserMessage:#"pop" data:#"Hey" completionHandler:^(SBDUserMessage * _Nullable userMessage, SBDError * _Nullable error) {
if (error != nil) {
NSLog(#"Error: %#", error);
return;
}
}];
}
- (void)channel:(SBDBaseChannel * _Nonnull)sender didReceiveMessage:(SBDBaseMessage * _Nonnull)message {
if (sender == self.channel) {
NSLog(#"From Button.Message Received From %# message is : %# in channel :",sender.description,message.description);
} else {
NSLog(#"Failed");
}
}
#end
Did you register your current class as the channel's delegate? You need to do this so that when the channel receives a message, it will call your delegate with the received message.
So in your class, I am assuming it's a UIViewController, declare it to conform to like so:
#interface OpenChannelViewController : ViewController<SBDChannelDelegate>
#end
Somewhere in your viewDidLoad, you should add this class to the channel delegate.
- (void)viewDidLoad {
[SBDMain addChannelDelegate:self identifier:UNIQUE_HANDLER_ID];
}
Now you should receive messages. Info was taken from here:
https://docs.sendbird.com/ios?_ga=1.152151677.594130729.1491427400#open_channel_3_receiving_messages
Good luck!
Using following code to get OAuth token but it always fails with error
Your credentials do not allow access to this resource
I have taken following code sample from
https://github.com/nst/STTwitter/blob/master/demo_cli/reverse_auth/main.m
Even I have allowed Read and Write access in application settings at
https://apps.twitter.com/app/XXXX/permissions
STTwitterAPI *twitter = [STTwitterAPI twitterAPIWithOAuthConsumerName:nil consumerKey:#"MY CONSUMER KEY" consumerSecret:#"MY CONSUMER SECRET"];
[twitter postReverseOAuthTokenRequest:^(NSString *authenticationHeader) {
STTwitterAPI *twitterAPIOS = [STTwitterAPI twitterAPIOSWithFirstAccount];
[twitterAPIOS verifyCredentialsWithSuccessBlock:^(NSString *username) {
[twitterAPIOS postReverseAuthAccessTokenWithAuthenticationHeader:authenticationHeader successBlock:^(NSString *oAuthToken, NSString *oAuthTokenSecret, NSString *userID, NSString *screenName) {
NSLog(#"REVERSE AUTH OK");
} errorBlock:^(NSError *error) {
NSLog(#"ERROR, %#", [error localizedDescription]);
}];
} errorBlock:^(NSError *error) {
NSLog(#"ERROR");
}];
} errorBlock:^(NSError *error) {
NSLog(#"ERROR");
}];
Any help, where I am going wrong.
I am using facebook SDK , and when I am trying to invite friend via facbook by using fb invite deep linking.
NSDictionary * getParam = #{
#"access_token":accessToken,
#"fields":#"canonical_url",
#"pretty":#(YES),
};
NSString * getCanoicalURL = [NSString stringWithFormat:#"%#/%#",FB_CANONICAL_API, fbAPILinkID];
[self GET:getCanoicalURL parameters:getParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject)
{
NSError *error;
FacebookLink * getResult = [MTLJSONAdapter modelOfClass:[FacebookLink class] fromJSONDictionary:responseObject error:&error];
if (error)
{
handler(nil,error);
}
else
{
handler(getResult.canonicalUrl,nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error)
{
handler(nil,error);
}];
The below is my invite friend method it show successfully :
-(void)inviteFriend:(NSString*)canonicalUrl
{
FBSDKAppInviteContent *content =[[FBSDKAppInviteContent alloc] init];
content.appLinkURL =[NSURL URLWithString:canonicalUrl];
[FBSDKAppInviteDialog showFromViewController:self withContent:content delegate:self];
}
But when I try to fetch for defer deep link it always null:
FBSDKAppLinkUtility fetchDeferredAppLink:^(NSURL *url, NSError *error)
{
NSLog(#"fetch defer app link :%#",url);
if (error) {
NSLog(#"Received error while fetching deferred app link %#", error);
}
if (url) {
[[UIApplication sharedApplication] openURL:url];
}
}];
Be sure that your iPhone's Limit Ad Tracking setting is off, at Settings -> Privacy -> Advertising
Get parts of a NSURL in objective-c
This will be ur exact reference and answer not so manual coding as above.
I'm using block for my APIs and the API class throws error via block like below code.
[HJHLifeAPI deletePlantWithIdentifier:identifier completionHandler:^(NSError *error) {
if (error) {
[[error alertView] show];
return ;
}
[self refresh:self.refreshControl];
}];
But the problem is that I use this pattern of codes in several places. As a result, I should write several duplicated codes for error handling. Is there any way to refactor this code? I think exception can be one solution, but I think Apple don't encourage developers to use it.
It's up to How your HJHLifeAPI is designed.
I usually use AFNetworking for API things and here's an example.
// This is the method like deletePlantWithIdentifier:
// It actually invoke __requestWitPath:
- (void)requestSomethingWithId:(NSString *)memId done:(NetDoneBlock)done
{
NSMutableDictionary *param_ = #{#"key":#"id"};
[self __requestWithPath:#"/apiPath.jsp" parameter:param_ done:done];
}
#pragma PRIVATE
- (void)__requestWithPath:(NSString *)apiPath parameter:(NSDictionary *)parameter done:(NetDoneBlock)done
{
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:SERVER_URL]];
AFHTTPRequestOperation *operation = [manager POST:apiPath parameters:parameter constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
done();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Error Handle Here
}];
[operation start];
}
You can handle all errors in one __request....
Create the block
void(^errorHandler)(NSError *error) = ^(NSError *error) {
if (error) {
[[error alertView] show];
return ;
}
[self refresh:self.refreshControl];
}
Save it somewhere (don't forget to copy it)
self.errorHandler = errorHandler;
Reuse it everywhere:
[HJHLifeAPI deletePlantWithIdentifier:identifier completionHandler:self.errorHandler];