Task parameter is nil in didCompleteWithError callback - nsurlsession

I'm trying to upload files using NSURLSessionUploadTasks and a background NSURLSession. The problem is that when the upload completes, the URLSession:task:didCompleteWithError: callback is invoked with a nil task parameter. The session parameter is not nil so no problem there. The task parameter is not nil in the URLSession:dataTask:didReceiveData: callback that is called prior to the completion callback. My test device is an iPhone 7 with iOS v11.0.

Related

how to prevent automatic answer of incoming call

i am following this Sinch example to design an app to app calling app: http://www.hnwatcher.com/r/1345925/Android-Use-the-Sinch-SDK-to-build-a-free-calling-app-in-30-mins and i have downloaded the sample app at github.
Everything is working fine except that the incoming call is being answered automatically. I would like the call be answered after the receiver clicks a button. How can i achive this?
When you app is notified of an incoming call then the following delegate method is called (I have copied this straight from the Sinch app to app call tutorial):
- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
// For now we are just going to answer calls,
// in a normal app you would show in incoming call screen
call.delegate = self;
_call = call;
[_call answer];
}
In this tutorial the call is meant to be answered straight away so we call
[_call answer];
to answer it.
To make the call answer at the push of a button you need simply move the above line of code out of this delegate method into a button action and it will work.
- (IBAction)answerButtonPressed: (UIButton *)button {
[_call answer];
}
Adding the above will mean that when a call comes in it won't be immediately answered and when you click the button the call will be connected.
Note: Don't forget to keep a pointer to the incoming call so that you answer the call as it is coming in. We can see this happening in the receive call method:
_call = call;

SKPaymentTransactionStateFailed, but no NSError

We have an app with IAP coin purchases. We've recently received mails from a few of our users, saying that they couldn't purchase any coins. I looked at their session logs and saw Failed IAP events, each with no fail reason logged. Here's the related code:
- (void)_purchaseRequestFailed:(SKPaymentTransaction *)transaction state:(StoreTransactionState)state error:(NSError *)error
{
IAPProduct *product = [self getProductWithId:transaction.payment.productIdentifier];
if (error.code==SKErrorPaymentCancelled) {
[_metricsManager logFailIAP:product failReason:#"Payment canceled"];
} else {
[_metricsManager logFailIAP:product failReason:error.localizedDescription];
}
if ([_delegate respondsToSelector:#selector(didSucceedPurchasingProduct:)]) {
[_delegate didFailPurchasingProduct:product];
}
}
inside logFailIAP, I log things like time, UDID, event name, and the error.localizedDescription.
if (failReason != nil && failReason.length > 0) {
[metricsDictionary setObject:failReason forKey:MetricsEventParameterFailReason];
}
In the logs, I'm getting Failed IAP events, but no logged reason for failing. Is there any case where, you get "SKPaymentTransactionStateFailed", but, have an empty error.localizedDescription? I can confirm that the logs work, and have seen errors like "Payment canceled", and "Cannot connect to iTunes" being logged in other devices. The issue is not specific to a device or iOS.
I have encountered a nil error in the following scenario:
User updates iOS on their device.
Immediately after the update, the user goes into your app and tries to make a purchase.
Instead of the usual purchase dialog, they get an "iTunes terms of service have changed. You need to accept new T&C's" (or something along the lines), which redirects them to the iTunes app and shows them the new T&C's. The payment is then cancelled and you get a nil error, and, obviously, a nil error.localizedDescription.
For this scenario to happen, your app needs to be the user's first point of interaction with the iTunes Store after the system update.

What can you do in CoreBluetooth background delegate calls?

I am using Core Bluetooth in my project. I have included Session Backgrounding to avail its background mode functionality. I have observed that the delegate for peripheral disconnection,
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
gets called in the background mode. However any code I write in this method is not executed except for NSLogs. Can somebody explain exactly what kind of code can be executed here?
My aim is to send this disconnection notification to my server.
Ok it seems it was some issue at my end. According the the documentation your app is woken (in the background) for around 10 seconds when it gets a bluetooth related delegate call.
You can use this time to perform any non view updating task and even request for additional time using beginBackgroundTaskWithExpirationHandler.
My code looks like this.
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
[self sendEmailInBackground:peripheral]; //Code to send a server request
return;
}
and its working in the background mode. This also works when the phone is in lock state.

Cocoa Custom URL Scheme selector not called first time

I am developing a Mac application which registers a custom URL scheme. The application launches but my selector method is not being called so I am not able to parse the URL. After the application is launched, subsequent URL scheme calls result in a call to the selector method.
I had the
[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
andSelector:#selector(getUrl:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
on AppDelegate applicationDidFinishLaunching and now moved it to the init method without any result.
Any ideas on how to solve it?
Actually, moving the event handler registration to the init method did the trick. In my case the URL was launching the XCode archived application instead of the newly archived one.

Websocket message interupts dynamic loading of ExtJS class

in my ExtJS 4.1 application I use a websocket connection to remotely insantiate and control ExtJS classes from the server. The client is registered to websocket.onmessage and is waiting for incoming commands.
I defined a simple protocol for that. The server sends a "CREATE classname id". On client side I use Ext.create to instantiate the class. The server then can send commands via the websocket to the object. E.g. "DOSTUFF id". I'm using the dynamic loading mechnism of ExtJS.
In Chrome everything works fine.
The problem with Firefox is, that the second command message (DOSTUFF) is executed BEFORE the object has been created. This leads to an error because the object cannot be found. It seems that the second websocket commandmessage is executed before ExtJS has loaded the file via HTTP-GET.
In my world JavaScript is executed sequentially (I don't use webworkers). I think the call of Ext.create(..) should be executed synchronously with the HTTP-GET in background, shouldn't it?
Here is a "pseudo" trace output of my client application:
ExecuteCommand (Enter): CREATE ("MyClass", "1")
HTTP-GET "MyClass.js"
ExecuteCommand (Enter): DOSTUFF ("1")
ExecuteCommand (Error): DOSTUFF ("1"): Object not found
ExecuteCommand (Enter): CREATE ("MyClass", "1"): OK! Object created!
It makes sense. The GET request is async by default see Firefox doc: https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
To avoid this issue check for object existence and if need be let the server know to resend in a few seconds, and repeat.
Ok, as mentioned by DmitryB the HTTP-GET works asynchronous. After the XMLHttpRequest is sent, the control is passed to the next websocket.onmessage.
I solved this problem by using Ext.require with a callback function before I call Ext.create.
It looks something like that:
ExecuteCommand: CREATE ("MyClass", "1")
Ext.require("MyClass", function(c) {
ExecuteCommand: DOSTUFF (c);
}

Resources