Write block functions in Swift - objective-c

How would I write this block function in swift. I've read through on the subject but the syntax just doesn't make much sense to me.
MyAppRequest *request = [_agent login];
[request sendWithLoadMessage:#"Signing In"
successMessage:#"Signed In"
failureMessage:#"Failed to log in"
recoveryOptions:#"If you keep having trouble, try going to http://mystrou.firehosehelp.com and try loggin in there. If that fails, try resetting your password"
success:^(MyAppResponse *response) {
PREFS.authToken = _agent.accessToken;
[_delegate loginViewController:self loggedInAgent:_agent];
} failure:^(MyAppResponse *response) {
}];

It's not that hard actually. called closures in Swift).
public func someFunction(success: (response: AnyObject!) -> Void, failure: (error: NSError?) -> Void) {
}
And here's how you call it.
someFunction(success: { (response) -> Void in
// Handle success response
}) { (error?) -> Void in
// Do error handling stuff
}
In your case, I'm getting this block handles some server response. Most probably logging in. The success block would be called if the network operation succeeds. Inside it, you save the received access token from your server.
The failure block is called if the network request fails. You might want to log the error out, display an alert to the user stuff like that in it.
If you're confused about the syntax I suggest refer to these two sites. For Objective-C block syntax and for Swift closure syntax.

thanks to #isuru I figured this out:
let request: MyAppRequest = agent .login()
request .sendWithLoadMessage("Signing in",
successMessage: "Signed in",
failureMessage: "Failed to login",
recoveryOptions: "Figuring it out",
success: { (response: MyAppResponse!) -> Void in MyAppSettings().authenticatingToken = agent.accessToken
}) { (response: MyAppResponse!) -> Void in
var alert = UIAlertController(title: "Oops!", message: "You haven't figured out the token thing!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}

Related

How to make notification clicks on apple devices redirect to links?

I am successfully able to send APNs to apple devices. I have coded up my app in react native. When someone clicks on the notification, I want to redirect them to a deep link I have configured my app to recognise - ne://page/id via deep linking, I don't need help with that. How do I redirect a notification click to a link ?
I have tried everything from my end. I looked at the official documentation here - it saysn nothing about urls and redirection - https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
Moreover, I have using the apn-node library to send notifications via my server. Their notification docs have no url option, just something called urlArgs.
set URL in the payload object of node-apn like this:
notification.payload = {
url: "https://www.google.com"
}
parse the URL from the userInfo object in didReceiveRemoteNotification delegate method of AppDelegate
Open the URL in an in-App WebView or Safari
For Further reference, after my response You can refer https://medium.com/#stasost/ios-how-to-open-deep-links-notifications-and-shortcuts-253fb38e1696 .
When the app is closed or running on the background more, tapping on the notification banner will trigger didReceiveRemoteNotification appDelegate method:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
This method will also be triggered when the app received a push notification while it is running in the foreground mode. Because we only considering the scenarios when you want to open the app on the certain page, we will not cover handling notifications in the foreground mode.
To handle the Notifications we will create a NotificationParser:
class NotificationParser {
static let shared = NotificationParser()
private init() { }
func handleNotification(_ userInfo: [AnyHashable : Any]) -> DeeplinkType? {
return nil
}
}
Now we can connect this method to the Deeplink Manager:
func handleRemoteNotification(_ notification: [AnyHashable: Any]) {
deeplinkType = NotificationParser.shared.handleNotification(notification)
}
And complete the appDelegate didReceiveRemoteNotification method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Deeplinker.handleRemoteNotification(userInfo)
}
The last step is to finish the parsing method in the NotificationParser. This will depend on your notification structure, but the basic parsing technic will be similar:
func handleNotification(_ userInfo: [AnyHashable : Any]) -> DeeplinkType? {
if let data = userInfo["data"] as? [String: Any] {
if let messageId = data["messageId"] as? String {
return DeeplinkType.messages(.details(id: messageId))
}
}
return nil
}
If you configured the app to support the push notifications and want to test it, here is the notification I am using to deliver a message:
apns: {
aps: {
alert: {
title: "New Message!",
subtitle: "",
body: "Hello!"
},
"mutable-content": 0,
category: "pusher"
},
data: {
"messageId": "1"
}
}

Angular GlobalErrorHandler and HttpErrorResponse - Resolver throwing badly formatted HttpErrorResponse

I've created global error handler in my Angular 6 application:
main error handler method:
handleError(error: Error | HttpErrorResponse) {
const router = this.injector.get(Router);
const notificationService = this.injector.get(NotificationsService);
this._logger(error);
if (!navigator.onLine) {
notificationService.displayNotification('error', 'timespan', {heading: 'Internet connection lost!', body: ''});
} else if (error instanceof HttpErrorResponse) {
notificationService.displayNotification('error', 'click', this._httpErrorMessage(error));
} else {
// CLIENT error
router.navigate(['/error-page']);
}
}
Problem:
Many of HTTP service calls are being performed in resolvers:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ClientDetailsModel> {
if (route.params.cif) {
const reqBody = new GetClientDetailsRequestModel({cif: route.params.cif, idWewPrac: this.userContext.getUserSKP()});
return this.clientsService.getClientDetails(reqBody)
.pipe(
map((clientDetails: { customerDetails: ClientDetailsModel }) => {
if (clientDetails.customerDetails) {
return clientDetails.customerDetails;
}
return null;
})
);
}
If Http error occurs in such a call, error received by my global error handler is formed as HttpErrorResponse wrapped inside Error (message of Error is HttpErrorResponse):
Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":400,"statusText":"OK","url":"https://...
If Http errors occurs outside of resolvers global error handler works perfectly fine.
To reach my goal (throwing HttpErrorResponse from resolver) I need to specify the way to handle error in error callback inside subscription, but I cannot do it because resolver is the one who manages subscription.
Is there a way to specify how resolver should handle errors?
I would like to avoid manual parsing of these wrapped errors.
I was searching for a solution, but could only create a work-a-round.
This will check for the HttpErrorResponse text and tries to parse the JSON which results into the real error object.
Not great at all, but better then nothing.
handleError(error: any): void {
console.error('Errorhandler catched error: ' + error.message, error);
// We need to have this little hack in oder to access the real error object
// The Angular resolver / promise wraps the error into the message, serialized as json.
// So we extract this error again.
// But first lets check if we actually dealing with an HttpErrorResponse ...
if (error.message.search('HttpErrorResponse: ')) {
// The error includes an HTTPErrorResponse, so we try to parse it's values ...
const regex = new RegExp('^.*HttpErrorResponse:\\s(\\{.*\\})$');
const matches = regex.exec(error.message);
if (matches !== null) {
// matches the regex, convert...
const httpErrorResponse = JSON.parse(matches[1]); // This is now the real error object with all the fields
this.handleHttpErrorResponse(httpErrorResponse);
} else {
// It contains HttpErrorResponse, but no JSON part...
this.toastr.error('There was an unknown communication error',
'Communication error',
{timeOut: 10000});
}
} else {
this.toastr.error('Unknown error occured',
'Well that should not happen. Check the log for more information...',
{timeOut: 10000});
}
}

Error handling in HAPI

Catch all and any errors in a hapi request lifecycle.
I have a signup handler,
public signup(request: Hapi.Request, reply: Hapi.Base_Reply) {
this.database.user.create(request.payload).then((user: any) => {
return reply({
"success": true
});
}).catch((err) => {
reply(Boom.conflict('User with the given details already exists'));
});
}
Now, I am catching the error, but I can't be always sure that I will get this error message only. What if there is an error in the database?
How to catch such database errors or any other unknown errors for all the requests. ???
Maybe you have to return the err.message in your reply like
reply(Boom.conflig(err.message))
or if you want to manage or manipulate the error you have to verify the type of error like
if (err instanceof DatabaseError) {
// manage database error
}
I figured out a way to handle such errors in Hapi.
What I was looking for was a PreResponse handler. Now, the PreResponse handler can log all the errors and I can throw a 500 error response.
What I am saying is by simply writing
reply(err)
I can send a 500 error and can catch this error using preResponse handler. Something like this,
server.ext('onPreResponse', (request: Hapi.Request, reply: Hapi.ReplyWithContinue) => {
const response = request.response;
if (!response.isBoom) { // if not error then continue :)
return reply.continue();
}
console.log(response);
return reply(response);
});

Blueimp fileupload() callbacks not called

I am using Blueimp fileupload() to post image files to a django-tastypie API.
The code below works correctly as far as the file is being uploaded:
$("#image").fileupload({
dataType: 'json',
start: function() {
console.log("start fileupload");
},
progress: function(e, data) {
console.log(data.loaded + " " + data.total);
},
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
done: function(e, data) {
console.log("done uploading file.");
}
});
$("#image").bind('fileuploadfinished', function (e, data) {
console.log("fileuploadfinished");
});
However, the done callback is never called. I tried binding the fileuploadfinished and that is also never called.
start and progress are both called as expected.
beforeSend is undocumented, but is needed by django-tastypie for SessionAuthentication - removing it doesn't change that done and fileuploadfinished is never called.
As it turns out, django-tastypie correctly returns a 201 status code. However, this status code is not considered a success by fileupload.
This code handles the status code manually:
$("#image").fileupload({
dataType: 'json',
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
complete: function(xhr) {
if (xhr.readyState == 4) {
if (xhr.status == 201) {
console.log("Created");
}
} else {
console.log("NoGood");
}
},
});
That means, the complete callback is called whether success or failure, and checking the readyState and status together can tell whether it succeeded.
There are some other ways to get this to work, however I think this is the best. More details here:
Data inserted successful but jquery still returning error
I was having the same problem. it is because you set your datatype 'json'.
Just leave this out or put it to plain and it will work.
Your server , or uploadhandler isn't return a json answer.

Unable to test Open Graph

I'm trying to create my own actions/objects. When checking with the debugger everything is fine, but when testing with my dev account I get this in my callback:
{"data":[]}
Is it good or not because I see anything in my timeline, news feed or ticker.
When testing with a test user I get this error:
{
"error": {
"message": "Call to a member function on a non-object",
"type":"BadMethodCallException"
}
}
What's wrong?
You are supposed to make POST request to facebook api something like below and make sure you have initialised FB:
var opts = {
animal : OBJECT_URL,
access_token: token
};
FB.api('/me/[MY_APP_NAMESPACE]:hunt', 'post', opts, function(response)
{
});