Rubymotion and Objective C getter blocks - objective-c

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

NSInvalidArgumentException, Cannot do a comparison query for type: (null)

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.

Send Bird didReceiveMessage Not Works

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!

OAuthTokenRequest using STTwitterAPI fails

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.

ios fetch defer deeplink always null objective c by using facebook sdk

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.

How can I refactor duplicated codes for error?

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];