StoreKit multiple transactions - xcode

I'm stucked solving problem with In-App Purchases using StoreKit framework for Mac OS. The problem is this:
1) I call addPayment method when purchase started
2) Then updatedTransactions method called twice with transaction state SKPaymentTransactionStatePurchasing. And after second call [[SKPaymentQueue defaultQueue].transactions count] returns 2.
3) When purchase completed updatedTransactions called third time with transaction state SKPaymentTransactionStatePurchased. And [[SKPaymentQueue defaultQueue].transactions count] returns 3.
4) Then I finishTransaction with state SKPaymentTransactionStatePurchased. But in defaultQueue still remain two transactions with SKPaymentTransactionStatePurchasing. They alive till the app terminates. When I launch app again the problem repeats.
Why so many transactions for only one addPayment call? And how this problem can be solved?

Make sure to call finishTransaction method after any of the below transaction state :
1) SKPaymentTransactionStatePurchased
2) SKPaymentTransactionStateFailed
3) SKPaymentTransactionStateRestored
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
Calling finishTransaction: on a transaction removes it from the queue.

Related

Check Auto-renewable InApp Purchase iOS

I am implementing Auto-renewable InApp Purchase for iOS. It is working fine for first month. But I am unable to know whether user's subscription is auto renewed or not means what is the status of current InApp Purchase.
After studying so many answers on StackOverflow, I am able to understand that I have to provide Restore button to Restore transaction. I have implemented it as well and it is giving my all transactions till date. So, I am unable to get my last transaction. So, please help to understand the status of last auto renewed transaction so that I shall be able to update the status on my server.
Below is the code I am using to restore my transaction:
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
and implementing its delegates as follows:
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSLog(#"%#",queue );
NSLog(#"Restored Transactions are once again in Queue for purchasing %#",[queue transactions]);
NSMutableArray *purchasedItemIDs = [[NSMutableArray alloc] init];
NSLog(#"received restored transactions: %zd", queue.transactions.count);
for (SKPaymentTransaction *transaction in queue.transactions)
{
NSString *productID = transaction.payment.productIdentifier;
[purchasedItemIDs addObject:productID];
NSLog (#"product id is %#" , productID.description);
NSLog (#"observationInfo is %#" , transaction.payment.productIdentifier.observationInfo);
// here put an if/then statement to write files based on previously purchased items
// example if ([productID isEqualToString: #"youruniqueproductidentifier]){write files} else { nslog sorry}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
NSLog(#"Restore Error... %#",error.description);
}
I guess transaction restore is not work if application is running and Transaction is renew. Please refer StoreKit Guide :-
After a subscription is successfully renewed, Store Kit adds a
transaction for the renewal to the transaction queue. Your app checks
the transaction queue on launch and handles the renewal the same way
as any other transaction. Note that if your app is already running
when the subscription renews, the transaction observer is not called;
your app finds out about the renewal the next time it’s launched.
After relaunch application, Transaction restore functionality work fine with restoring current auto-renewed transaction.
On Alternate, If you want to check transaction is renewed or not without relaunch application, You can do with manually refreshing "App Receipt".
Link (Expiration and Renewal) :- https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html

Spring #Async cancel and start?

I have a spring MVC app where a user can kick off a Report generation via button click. This process could take few minutes ~ 10-20 mins.
I use springs #Async annotation around the service call so that report generation happens asynchronously. While I pop a message to user indicating job is currently running.
Now What I want to do is, if another user (Admin) can kick off Report generation via the button which should cancel/stop currently running #Async task and restart the new task.
To do this, I call the
.. ..
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone())
future.cancel(true);
service.generateReport(id);
How can make it so that "service.generateReport" waits while the future cancel task kills all the running threads?
According to the documentation, after i call future.cancel(true), isDone will return true as well as isCancelled will return true. So there is no way of knowing the job is actually cancelled.
I can only start new report generation when old one is cancelled or completed so that it would not dirty data.
From documentation about cancel() method,
Subsequent calls to isCancelled() will always return true if this method returned true
Try this.
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone()){
boolean terminatedImmediately=future.cancel(true);
if(terminatedImmediately)
service.generateReport(id);
else
//Inform user existing job couldn't be stopped.And to try again later
}
Assuming the code above runs in thread A, and your recently cancelled report is running in thread B, then you need thread A to stop before service.generateReport(id) and wait until thread B is completes / cancelled.
One approach to achieve this is to use Semaphore. Assuming there can be only 1 report running concurrently, first create a semaphore object acccessible by all threads (normally on the report runner service class)
Semaphore semaphore = new Semaphore(1);
At any point on your code where you need to run the report, call the acquire() method. This method will block until a permit is available. Similarly when the report execution is finished / cancelled, make sure release() is called. Release method will put the permit back and wakes up other waiting thread.
semaphore.acquire();
// run report..
semaphore.release();

What is considered overloading the main thread?

I am displaying information from a data model on a user interface. My current approach to doing so is by means of delegation as follows:
#protocol DataModelDelegate <NSObject>
- (void)updateUIFromDataModel;
#end
I am implementing the delegate method in my controller class as follows, using GCD to push the UI updating to the main thread:
- (void)updateUIFromDataModel {
dispatch_async(dispatch_get_main_queue(), ^{
// Code to update various UI controllers
// ...
// ...
});
}
What I am concerned about is that in some situations, this method can be called very frequently (~1000 times per second, each updating multiple UI objects), which to me feels very much like I am 'spamming' the main thread with commands.
Is this too much to be sending to the main thread? If so does anyone have any ideas on what would be the best way of approaching this?
I have looked into dispatch_apply, but that appears to be more useful when coalescing data, which is not what I am after - I really just want to skip updates if they are too frequent so only a sane amount of updates are sent to the main thread!
I was considering taking a different approach and implementing a timer instead to constantly poll the data, say every 10 ms, however since the data updating tends to be sporadic I feel that it would be wasteful to do so.
Combining both approaches, another option I have considered would be to wait for an update message and respond by setting the timer to poll the data at a set interval, and then disabling the timer if the data appears to have stopped changing. But would this be over-complicating the issue, and would the sane approach be to simply have a constant timer running?
edit: Added an answer below showing the adaptations using a dispatch source
One option is to use a Dispatch Source with type DISPATCH_SOURCE_TYPE_DATA_OR which lets you post events repeatedly and have libdispatch combine them together for you. When you have something to post, you use dispatch_source_merge_data to let it know there's something new to do. Multiple calls to dispatch_source_merge_data will be coalesced together if the target queue (in your case, the main queue) is busy.
I have been experimenting with dispatch sources and got it working as expected now - Here is how I have adapted my class implementation in case it is of use to anyone who comes across this question:
#implementation AppController {
#private
dispatch_source_t _gcdUpdateUI;
}
- (void)awakeFromNib {
// Added the following code to set up the dispatch source event handler:
_gcdUpdateUI = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0,
dispatch_get_main_queue());
dispatch_source_set_event_handler(_gcdUpdateUI, ^{
// For each UI element I want to update, pull data from model object:
// For testing purposes - print out a notification:
printf("Data Received. Messages Passed: %ld\n",
dispatch_source_get_data(_gcdUpdateUI));
});
dispatch_resume(_gcdUpdateUI);
}
And now in the delegate method I have removed the call to dispatch_async, and replaced it with the following:
- (void)updateUIFromDataModel {
dispatch_source_merge_data(_gcdUpdateUI, 1);
}
This is working absolutely fine for me. Now Even during the most intense data updating the UI stays perfectly responsive.
Although the printf() output was a very crude way of checking if the coalescing is working, a quick scrolling back up the console output showed me that the majority of the messages print outs had a value 1 (easily 98% of them), however there were the intermittent jumps to around 10-20, reaching a peak value of just over 100 coalesced messages around a time when the model was sending the most update messages.
Thanks again for the help!
If the app beach-balls under heavy load, then you've blocked the main thread for too long and you need to implement a coalescing strategy for UI updates. If the app remains responsive to clicks, and doesn't beach-ball, then you're fine.

IOBluetooth event delegates only execute in an unwanted NSRunLoop

I have a Cocoa app which launches a new NSThread (Thread A) from within applicationDidFinishLaunching.
Thread A successfully creates an RFCOMM connection then spawns another NSThread (Thread B), passing the established IOBluetoothRFCOMMChannel to Thread B.
Thread B creates a IOBluetoothRFCOMMChannelDelegate and calls setDelegate on IOBluetoothRFCOMMChannel with it and then runs its current NSRunLoop.
Thread A then waits for Thread B to signal a sync object.
The intent is that, when data arrives, Thread B's NSRunLoop will execute the delegate which copies the received data and signals Thread A to read it.
However, the delegate never gets called because Thread B's NSRunLoop has no input sources.
I imagined that setDelegate would create an input source on it.
The only way I can get the delegate called is if I have Thread A wait on its own NSRunLoop instead of wait on the sync object. In that case, the delegate gets executed.
But that arrangement will not work for me. Eventually, my code will just be a library that exposes a C API that is a standard and is only suitable as a procedurally flowing set of functions. Thread A will be someone else's Thread (maybe main maybe not) and will call into my library in a procedural way.
1) I thought that the thread/runloop which registered for a delegate callback (Thread B) was the one that would get the input source and execute the callback in its runloop. But Thread A's NSRunLoop gets the input source instead, Why? What's the expected relationship between these things?
2) How can I get Thread B to get the input source and be the thread that executes the delegates?
Thanks for any and all help.
My Thread B is below:
#implementation CBaiHardwareBluetoothEventThread
- (void) runEventThread: (IOBluetoothObjectID)deviceID
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
CallbackDelegate* cd = [[CallbackDelegate alloc] init];
IOBluetoothRFCOMMChannel* myOBJCChannel = [IOBluetoothRFCOMMChannel withObjectID:deviceID];
[myOBJCChannel setDelegate:cd];
do{
[myRunLoop runUntilDate:[NSDate distantFuture]];
cout << __FUNCTION__ << " this should not be returning but it is ???" << endl;
usleep(1000000);//avoid the unintentional hard loop that happens
}while(1); //forever for now
[pool release];
}
#end
IOBluetooth and threading is messy. You'll have to work this stuff out by trial and error. If it seems that the callbacks happen on the thread that opened the connection, then you'll have to open the connection on the thread where you need the callbacks. Also, this behavior often changes between OS releases...

Updating UI in Cocoa from another .m file

I have a GUI app that has a main thread and then I use NSOperation to run 2 other threads once the user clicks the Start button. Now one thread calculates a certain value and updates it. What I want thread 2 to do is to pick this value up and update the UI.
How do I get a IBOutlet Textfield value to get updated on the UI from this second thread ?
eg:
main.m --- handles the UI and has code to start the 2 threads when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
I am unable to accomplish the thread2.m task and update the UI. My issue is that how do I define a IBOutlet and update it with a value from thread2/1 so that the main.m has access to this value and updates the UI. I have access to the actual variable in main.m and can print it out using NSLog. Its just that I am getting stuck on how to update the UI with this value. As I need to have theIBOutlet in main.m to tie it with the UILabel in the app. Any ideas guys ? Thanks.
Could you add pointers to your thread1.m and thread2.m files? Then set them with either a constructor method or some accessor methods?
If I understand the situation you described in your example, and assuming what you are calculating is an int (you can modify as you need):
Add an accessor to thread1.m
-(int)showCurrentCalcValue
{
//Assume that you get calculatedValue from whereever else in your thread.
return calculatedValue;
}
Then add to thread2.m
NSTextField *guiTextField;
Thread1 *thread1;
-(void) setThread: (Thread1 *aThread)
{
self.thread1 = aThread;
}
-(void) setGuiTextField: (NSTextField *aTextField)
{
self.guiTextField = aTextField;
}
-(void) updateGUI()
{
[guiTextField setStringValue: [thread1 showCurrentCalcValue]];
}
Presuming your main.m is something like the following:
IBOutlet NSTextField *outputDisplay
-(void) setUpThreads()
{
Thread1 *thread1 = [[Thread1 alloc] init];
Thread2 *thread2 = [[Thread2 alloc] init];
[thread2 setGuiTextField: outputDisplay];
[thread2 setThread: thread1];
//Whatever else you need to do
}
Then just take care of setting everything and calling the methods in your threads.
Source code files don't matter. You could have all of this stuff in one file (not that that would be a good idea) and the problem would be unchanged. What matters are the classes.
Classes are not simply bags of code; you design them, you name them, and you define each class's area of responsibility. A class and/or instances of it do certain things; you define what those things are and aren't.
When writing NSOperation subclasses, don't worry about the threads. There's no guarantee they even will run on separate threads. Each operation is simply a unit of work; you write an operation to do one thing, whatever that may be.
eg: main.m --- handles the UI and has code to start the 2 threads —
operations
— when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
That's not one thing; that's an indefinite sequence of things.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
You should not touch the UI from (what may be) a secondary thread. See the Threading Programming Guide, especially the Thread Safety Summary.
I don't see why this should even be threaded at all. You can do all of this much more easily with an NSTimer running on the main thread.
If it would be inappropriate to “calculate… a particular value” on the main thread, you could make that an operation. Your response to the timer message will create an operation and add it to your computation queue. When the user hits stop, that action will go through on the main thread; invalidate the timer and wait for the queue to finish all of its remaining operations.
With either solution, “thread2.m” goes away entirely. Your update(s) to the UI will (and must) happen entirely on the main thread. With the latter solution, you don't even have to wait until you're done; you can update the UI with current progress information every time you receive the timer message.

Resources