I have been working for a while to give my app a "Pro Version" with more features. I have been following Apple's StoreKit Guide to make this happen but there is a tiny concern I have regarding persisting the transaction receipt of a completed IAP.
If you scroll down to page 27 of the document I linked to above you will find a code snippet that contains the following line:
NSData *newReceipt = transaction.transactionReceipt;
The concern I have is that the transactionReceipt property is deprecated as of iOS 7.
I hate using deprecated code. And in this case it is a big problem because if Apple's documentation isn't updated to reflect changes for iOS 7, where am I supposed to get instructions to make this work 'properly'?
You should be able to pull down your receipts like this (untested):
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt = [NSData dataWithContentsOfURL:url];
Related
I was using ShareKit for a p long time, without downloading last updates from its repository.
Now i need some of its new features, so i've pulled all last commits and tried to run my app with new ShareKit without making any changes to my code (except some small changes in includes).
App compiles without errors but when i try to execute usual Facebook sharing code - it crashes without any useful error description.
old code i want to get to work
NSURL *url = [NSURL URLWithString:[NSString stringWithUTF8String:sk::game_services::get_app_store_url()]];
SHKItem *item = [SHKItem URL:url title:[NSString stringWithUTF8String:message] contentType:SHKURLContentTypeWebpage];
[SHKFacebook shareItem:item];
and according to updated ShareKit demo app and its documentation - this code should still work.
but it doesn't
it horribly crashes in currentIndicator method of SHKActivityIndicator inside macro DEFINE_SHARED_INSTANCE_USING_BLOCK that contains dispatch_once call.
debugger just says "SIGABRT" and thats all.
i don't know what to do.
For a given MPMediaItem representing a track in an iOS5 user's music library, how can we determine if a track is:
an iTunes Match track that has not been downloaded from iCloud
vs.
a DRMed track
?
In both cases the NSURL returned by MPMediaItemPropertyAssetURL is nil. Therefore instantiating an AVAsset to check the exportable flag is not a viable solution.
It's my understanding that it depends on the version of iOS you use. I think prior to maybe 4.3, an asset returning nil meant simply that the item was DRMed and you didn't have access to it. However, in current versions (5), nil means it's iCloud only. Maybe you have tracks that you think are just DRMed but are in fact iCloud stored songs. On the current app I'm working on, I originally didn't account for iCloud tracks at all (as I was targeting the app for prior versions of iOS) and so I was getting crashes depending on who's device I used. To solve the issue and test for iCloud/DRM I use:
AVURLAsset* asset;
NSURL* realAssetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
if(!realAssetUrl){
//track is iCloud
}
asset = [[AVURLAsset alloc]initWithURL:realAssetUrl options:nil];
if(asset == nil || asset.hasProtectedContent){
//asset is DRMed such that it cannot be played back.
//most apps can stop here but I need to be able to export the song
}
if (!asset.exportable || !asset.readable){
//the asset cannot be exported and thus cannot be cached to a file
//the current app directory and cannot be transferred over network
//if asset passed earlier check, can still be used for local playback
}
[asset release];
That seems to work fine for me, but you also imply you were headed down the same path, already, so I'm not sure how much help that'll be to you. However, good luck with your project and I hope you find the answer you're looking for!
I'm trying to do a lightweight migration of a SQLite store in Core Data. Working on Lion 10.7.3 with Xcode 4.3.1.
In my NSPersistentDocument subclass (AccountDocument), I've overridden the method used to configure the persistent store coordinator so that it gets the proper options for the migration:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newStoreOptions;
if (storeOptions == nil) {
newStoreOptions = [NSMutableDictionary dictionary];
}
else {
newStoreOptions = [storeOptions mutableCopy];
}
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
return result;
}
(Thanks to Malcolm Crawford for that tip: http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)
When I run the app, it fails in NSPersistentDocument's implementation of -managedObjectModel:
* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298
From what I can tell from the documentation, the default implementation looks something like this:
- (id)managedObjectModel
{
NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
return result;
}
So to debug the problem a little more, I overrode that method with this:
- (id)managedObjectModel
{
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:#"AccountDocument2" withExtension:#"momd"];
NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];
return result;
}
(Thanks to Jeff LaMarche for the idea: http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html)
The bundle and url both point to the places I expect (and I've followed Marcus Zarra's advice to clean the project so there aren't any stray .mom or .momd bundles in the application package: Using mergedModelFromBundles: and versioning (CoreData)). Yet the app continues to crash while loading the model from the url.
I've checked that the AccountDocument2.xcdatamodeld is a package that has two models for versioning: AccountDocument 2.xcdatamodel and (the original) AccountDocument.xcdatamodel. The "Versioned Core Data Model" popup menu in the file properties is set to "AccountDocument 2".
The only difference between the two models is that one Entity has an additional (and optional) Attribute. My understanding is that qualifies the model for a lightweight migration.
Obviously, I'm doing something wrong here, but I have no idea what. Any help would be most appreciated…
Update:
Per Martin's suggestion (and a check of the NSPersistentDocument documentation) I tried using this code for the accessor:
- (id)managedObjectModel
{
static id sharedManagedObjectModel = nil;
if (sharedManagedObjectModel == nil) {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:#"AccountDocument2" withExtension:#"momd"];
sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
}
return sharedManagedObjectModel;
}
Still crashing…
Update
After some suggestions on Twitter, I upgraded to Xcode 4.3.2, but the problems persist.
RAGE UPDATE
I just created the versioned model package (AccountDocument2.xcdatamodeld) using Xcode 4.2 on Snow Leopard. After building and running the app, everything works as expected.
I then took the AccountDocument2.xcdatamodeld file package back over to Lion and Xcode 4.3.2. When I build and run the app, it continues to crash while loading the .momd resource. Yes kids, that means Xcode 4.3.x and the Data Model Compiler (MOMC) are to blame. I don't see a workaround other than doing all my builds on Snow Leopard.
I'm not one to bash Xcode 4, but when we find ourselves in a situation where the toolchain can't produce an opaque file (.mom and .momd) from an opaque specification (.xcdatamodel and .xcdatamodeld) it's pretty hard to be upbeat about the state of Mac and iOS tools. It's ridiculous that a core component of these platforms breaks to the degree where I can't build and run my app on the latest version of the SDK and developer tools.
It's Come To This Update
More proof that this is a serious bug with the Data Model Compiler (MOMC) in Xcode 4.3.2: if I copy the .momd bundle from the Resource folder created by Xcode 4.2 into my project and add them to the build as a Copy Files build phase, the application works fine.
I also did some tests where I removed validation rules and default values for the Attributes of the various Entities (based on Marcus' suggestion below.) No change, the compiler still creates an invalid .momd. I also tried creating a versioned model where NOTHING was changed: the compiled .momd continued to crash. So whatever you have in your current models (and data they represent) is the source of the problem.
Also of note: this bug is not isolated to NSPersistentDocument (as I originally thought when I started this question.) I can cause an app to crash by just using [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL].
For now, I'll be editing/versioning my models using Xcode 4.2 on Snow Leopard and moving the compiled resources over to Xcode 4.3.2 on Lion. If you use Core Data in any way, I suggest you do the same until this bug is addressed. Trust me, you'll spend days trying to figure out what the hell is going on if you don't.
Now to submit a Radar…
Radar Update
I just submitted this Radar:
http://www.openradar.me/11184500
The Oh Crap It Must Be Lion Update
I just downloaded and installed the Xcode 4.2 for Lion tools from http://developer.apple.com/downloads. The sample application used in the Radar still crashes.
(Note: you can't install Xcode 4.2.1 because the certificate used to sign the DeveloperTools.pkg has expired. Only Xcode 4.2 will work.)
If you're under NDA you'll also find that the beta tools aren't helpful either.
Hope you have a copy of Snow Leopard with Xcode 4.2 sitting around: http://furbo.org/2012/03/28/vmware-for-developers/
The WTF Do Fetch Requests Have To Do With Versioned Entities and Attributes Update
Via Evadne Wu on Twitter:
https://twitter.com/#!/evadne/status/187625192342818818
And how she did it:
https://twitter.com/#!/evadne/status/187629091518816258
(.mom files are binary plists.)
The root of the problem is a single Fetch Request. How that figures into a migration of data from one model to another is for an engineer at Apple to figure out.
The compiled .momd resources can be loaded after an "existingPartner" fetch request is changed from:
name == $name
to:
name == $NAME
It's counterintuitive that a part of the object model that does not affect the persistence of data breaks versioning and lightweight migration. It's clear from the documentation that this should not be the case:
Core Data’s perspective on versioning is that it is only interested in features of the model that affect persistence.
Use the power of the CHOCKLOCK to fix your Fetch Requests or delete them completely and rely on NSPredicates created in code.
I think you need to store the managed object model in an instance variable. You are returning an autoreleased object, which is what is probably causing the bad access.
Based on your theory that it is an issue with the MOMC, Do you have any validation rules in the mom?
I have seen reports where validation rules do not survive the 4.x MOMC.
This might be somewhat related to an issue I had with using Fetch Requests when iOS5 first came out in beta. It was causing a build warning and would crash the app on launch. I wasn't really using the fetch request so I removed it and everything worked fine:
Core Data warning: "Version hash information not available for all models"
At the stage of testing applications iCloud works fine. But after the application checks for updates from apple and download from itunes, icloud is not working, then there is a line
NSURL * returnedURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil];
returns nil.
Where did I go wrong?
Thanks in advance.
Are you sure your containers are listed in the com.apple.developer.ubiquity-container-identifiers entitlement?
Apple's Documentation on NSFileManager URLForUbiquityContainerIdentifier: mentions:
If you specify nil, this method returns the first container listed in the com.apple.developer.ubiquity-container-identifiers entitlement.
I need some help in using the NSURLCache to download a simple file. It would need to be saved in the Documents folder of the app. I have seen the URLCache example that apple presented, but I didn't find it useful since it was an image that was being shown. In addition there was some complex code on the modification date. I actually need something when the application opens it will begin the download process. Can someone guide me through just the download process of any file?
Thanks
Kevin
NSURL *myURL = [NSURL urlWithString:#"http://www.google.com/theInternet.zip"];
NSData *myData = [NSData dataWithContentsOfURL:myURL];
[myData writeToFile:#"ThePath" atomically:YES];
This will block, but should be ok for small downloads. If you are going to be downloading something that is many megabytes then look into asynchronous downloads. You can see an example here:
http://github.com/erica/iphone-3.0-cookbook-/tree/master/C13-Networking/07-Asynchronous%20Downloads/