1

How to run code on app for iOS only one time (even the application will be removed and reinstalled)?

For example, we need to make a gift for all new users. But if you use it you have to buy it again using in-app purchase.

Dmitry
  • 14,306
  • 23
  • 105
  • 189
  • "For example, we need to make a gift for all new users. But if you use it you should buy it again using in-app purchase." - So you want to run it **once** or **multiple times?** –  Feb 22 '13 at 14:54

2 Answers2

3

You can store a flag in the keychain. That persists on the device even after the app has been deleted. You could also use an iCloud key-value setting which could be used for control over multiple devices on the same account.

here's an example of adding info (in this case whether or not the user had purchased something) to the keychain and getting it back out.

    static NSString *kIAPKeyChainDescription =  @"MyAppPurchaseKey";

    static NSString *kPurchaseTag = @"YES";
    + (void)recordTransaction:(NSString *)productId
    {

        NSMutableDictionary* dict = [NSMutableDictionary dictionary];
        NSData *tag = [kPurchaseTag dataUsingEncoding:NSUTF8StringEncoding];

        [dict setObject: (id) kSecClassGenericPassword  forKey: (id) kSecClass];
        [dict setObject: kIAPKeyChainDescription forKey:(id) kSecAttrDescription];
        [dict setObject: productId      forKey: (id) kSecAttrService];
        [dict setObject: tag  forKey: (id) kSecValueData];


        OSStatus result = SecItemAdd ((CFDictionaryRef) dict, NULL);

        if (result != 0)
        NSLog(@"SecItemAdd error code is %ld",result);
    }


    + (BOOL)isPurchased:(NSString *)productId
    {
        NSMutableDictionary* query = [NSMutableDictionary dictionary];

        [query setObject: (id) kSecClassGenericPassword forKey: (id) kSecClass];
        [query setObject: productId forKey: (id) kSecAttrService];
        [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

        NSData* upgradeItemData = nil;
        OSStatus result = SecItemCopyMatching ( (CFDictionaryRef) query, (CFTypeRef*) &upgradeItemData );

        if (result != errSecSuccess && result != errSecItemNotFound){
            NSLog(@"SecItemCopyMatching errcode is %ld",result);
            return NO;
        }

        if ( !upgradeItemData || result == errSecItemNotFound)
        {
            return NO;
        }
        else
        {
            NSString* s = [[[NSString alloc] 
                            initWithData: upgradeItemData 
                    encoding: NSUTF8StringEncoding] autorelease];

            [upgradeItemData release];

            return [s boolValue];
        }
    }
Mike M
  • 4,358
  • 1
  • 28
  • 48
0

You will have to make a web service for it i dont think any other way out. Save device token.

amar
  • 4,285
  • 8
  • 40
  • 52
  • There are free in-app purchases on the AppStore. But we need to process it without user interaction. – Dmitry Feb 22 '13 at 14:57
  • hit a service in background and save the device token once and for ever design some ninja algo to make search faster every time a new instalation takes place for older ones use userdefaults – amar Feb 22 '13 at 15:00