Tuesday, August 6, 2013

“Can't find model for source store” - Core Data Migration



I was tearing my hair out over the "Can't find model for source store"  && "Cannot create an NSMigrationManager with a nil source model".error for a whole day.

Problem Description :

I have a app Zitrr Camera 1.1 which is already on app store. Now in Version 1.3 of the app , i am trying to run core data migration on it but it seems to be unable to find the source object model no matter what. I searched google, stackoverflow tried many things, but no success.

Version 1.1 Core Data Model : (Old One)




Version 1.3 Core Data Model : (Updated One)





NOTE : I have created only one Entity "ZNCAsset" in my Zitrr Camera Project.

What i Tried:

-  Core Data Versioning and Migration to do it automatically. I created a new version of the model and set it as the current version and called addPersistentStoreWithType:configuration:URL:options:error: with NSMigratePersistentStoresAutomaticallyOption, NSInferMappingModelAutomaticallyOption. but no luck.

- Since the automatic migration seems not to work in any way,  I tried manual migration . I extracted the metadata and checked if model is compatible. then find the suitable source moderl for the store via mergedModelFromBundles:forStoreMetadata:. Same as before Source model still nil.

i can delete my old datamodel file  and start fresh as need to migrate my Version 1.1 customer's data.

                                                             Stuck :( !

Solution For Above Problem, "From No Luck to Luck"!

I started debugging at version 1.3. when i Printed metadata of store by using NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
  URL:url error:&error it looked like :





But i created only one Entity "ZNCAsset" in Zitrr Camera. From where these TKBlog, TKPhoto,TKChat ... TKUser etc came from? i don't have any datamodel  in Version 1.3 that describes Entities like TKBlog, TKPhoto etc. So I Opened my Code of Version 1.1 and searched their and 

                                                             BINGO!
    
Actually In Version 1.1 i Used thirdParty Library "TumblrAPI". Which had a file "TumblrKit.xcdatamodeld" , which have Entity like  TKBlog, TKPhoto etc Entity. As we dropped Support of Tumblr in  Version 1.3 , So i Deleted All Files From Projected related to Tumblr API  including "TumblrKit.xcdatamodeld". So now I added back only "TumblrKit.xcdatamodeld" file  to version 1.3 and run it over version 1.1 and now its just started working fine like old days.


Why This Problem Occured :


this is because side effect of code

NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:sourceMetadata];

which  will create a model containing entities from my main model as well as my other model  linked to the application (here Tumblr Model).  Above Code has Pulled All extra Entity From Tumblr in Version 1.1 and stored it As a metadata of Store, but now when in New Version 1.3 Source Model is Created Using 

NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:sourceMetadata];

As  Source Metadata have that tumblr Entity information, but  don't have model ("TumblrKit.xcdatamodeld")file in Version 1.3 as (Tumblr data model file is got deleted in this version). So it not able to create source model from source store.






Sunday, May 26, 2013

How to Test inApp Purchase on sample code "In App Rage"



1. create Testing user in itunes connect but never put in itunes login else you will get error and need to create new one.
2. this approach uses "Sandbox Testing" so you will not charged anything.
3. you can do in app testing without affecting any of your app in App store.
                                                      #Thanks  raywenderlich #

1. Registering a new App ID for testing Only 

1.log into the iOS Developer Center, select the “Identifiers->App IDs” tab, and click  + button for “New App ID”.
    


2.  As an Example put Following Value in App ID Description :

      Name:   like "In App Rage ID"  
      Enable Services: In-App Purchase
       Explicit App ID :  use a reverse-domain name style here example  "com.razeware.inapprage".
       Don't Use Wildcard App id.
  
   Submit ,viola – you have a new App ID! 
  

2. Create a new  Provisioning Profiles for this App ID

1. go to  iOS Developer Center, Select Provisioning Profiles .
2. click + Button .
3. Select Development -> iOS App Development,Continue.
4. Select App ID - > select "com.mycompany.mytestapp" from dropdown.
5. Select certificates -> Select your/developer name.
6. Select devices.
7. Name this profile and generate.

3. Add new App in Itunes Connect for above App ID

1. go to itunesconnect -> Manage Your Apps - > Add new app .

     Then enter in an App Name, SKU number, and choose the Bundle ID you just made as shown  below:

 

  APP Name : Need to be Unique.
  SKU Number : Anything (Only for you)
  Choose Bundle id : You just Created.

2.  The next two pages will ask you for your app’s information. put in placeholder information for now – you can change all of this later.
      upload  ScreenShot if u dont have, you can use this dummy Screenshot..no need to upload any binary file. 

3. now you can see your app in itunes. 




4. Add new In App Purchases




 



  • Consumables. This means things you can buy more than once and can be used up, like extra lives, in-game currency, temporary power-ups, and the like.
  • Non-Consumables. This means something that you buy once, and expect to have it permanently. This means things like extra levels, unlockable content, and the like.
For my case  Once the user purchases them, they should always have them, so choose Non-Consumable.




Next, you will be taken to a page to enter some information about your In-App Purchase. Fill in the fields according to the screenshot below:




Let’s cover what each of these fields means:
  • Reference Name: This is what shows up in iTunes Connect for this in-app purchase. It can be whatever you want since you won’t see it anywhere in the app.
  • Product ID: Also known as “product identifier” in the Apple docs, this is the unique string that identifies your in-app purchase. Usually it’s best to start out with your bundle id, and then append a unique name for the purchase at the end.
  • Cleared for Sale: If this in-app purchase is OK for users to purchase as soon as the app becomes available.
  • Price Tier: How much this in-app purchase should cost.
After you’ve set that up, scroll down to the Language section and click Add Language. Fill out the form that pops up with the following information:

Create 4/5 Entry for In App Purchase like : 

Create Test User:
  1. Select “Manage Users” on the iTunes Conect home page
  2. Select “In App Purchase Test User”
  3. Select “Add New User”.
  4. dont use any email id which is already registered on itunes, as u can not use this testing id  to purchase any item and.
    "dont ever put this email id in app store itunes else u will get error: 

    Error Domain=SKErrorDomain Code=0 “Operation could not be completed. (SKErrorDomain error 0.)”

    " at testing time and then u need to create new Testing id. as it happend to me also  and taken lot of time! :( 
  5. Use it only at time testing time when pop up for account and password appears.  
           
     

  5.  Download Source Code From here 

1. open code in Xcode and Update with Provisioning profile created in 2 step. (xcode -> organizer-    >Library->provisioning profile->refresh ).
2.  update code sign.
3. update target with your build identifier , created in step 1 like "com.razeware.inapprage".
4.  Search this in code :
   /* NSSet * productIdentifiers = [NSSet setWithObjects:
                                      @"com.razeware.inapprage.drummerrage",
                                      @"com.razeware.inapprage.itunesconnectrage",
                                      @"com.razeware.inapprage.nightlyrage",
                                      @"com.razeware.inapprage.studylikeaboss",
                                      @"com.razeware.inapprage.updogsadness",
                                      nil];*/

 with your in App product identifier you created in  step 4.

and Now Run the app and you are done.

Reference:
1.http://www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios-6-tutorial/