Thursday, April 12, 2012

How To: Setup Linkshare for iOS Developer

What is Linkshare for iOS Developers?
Linkshare is a way for you to make some EXTRA money from your app sales!
As you know, for each app sold, Apple will take 30% and you will take 70%.
With Linkshare, you will get an extra 4-5%! Want that extra 4-5%? Read on!


I was trying to find a step by step tutorial for joining the affiliate program of iTunes/App Store via LinkShare.com, but couldn't find any (most of them are dead links and some requires you to buy their e-book). I have successfully registered with them, activated the account with email confirmation (just click a link in the email that they sent after completing the registration forms). Then I was stuck. Not sure where to begin. Took me a few hours to figure things out, so I'd like to share this tutorial, especially for international developers who would like to implement Affiliate program with LinkShare.

I will assume you have already successfully registered with LinkShare.com, and that you have completed the online registration forms, submitted it, and activated the account through your email. So next, login to your account and then:

1. Apply For the iTunes / App Store Program within LinkShare.com.
a) At the top menu bar, there is a PROGRAM button. Click on it.


b) A list of Categories will show up. At the right hand corner, there is a search field. Search for "iTunes".

c) The iTunes/App Store Program will show up and click Apply button at the end column.


d) Wait for 1-2 weeks for the application process by LinkShare/Apple. They will review your website and so on.

*continue.

e) It just took me about 3 days to be approved by Apple/LinkShare. Awesome. So next, what we do is click on the My Advertisers tab under the Programs section. Then go ahead and click the iTunes & App Store link listed there.


f) Then you will be shown the iTunes Create Links page. Spot the Link Maker Tool, and click that (see below)


g) This will bring you to the iTunes Link Maker tool (hosted by Apple). Use the BULK function, whereby you can paste multi links of your apps into the text area and all will be converted to the Affiliate links at once.
Follow the steps indicated below:

h) As you will notice, the affiliate link is a very long one. You can just use it like that, or you can also use shortening URL services such as http://bit.ly. Bit.ly is some sort of a redirect service. It keeps your URL short.

For example is this link to my app iHueSplash.

There you go. That is all there is to it. Pretty simple really. But wait, how to use these URLS/iTunes Affiliate Links?

As for me, I put it in my signature of forums post, I use it in my website too. Also, I even use it in my apps (where user tap the links to get a Pro version and so on). You can also put it in Links that you post to promote your app in iPhone Apps Review sites/forums.

BUT (here is a big BUT), do not ever use these URLs posted in your Press Release. PRMac, specifically are against this, and I believe so does other press release. Redirects are not good for Press Releases.

You will be getting somewhere around 4-5% of your app sales from this affiliate. Not much really. But hey, it's still money isn't it? If you have any questions, just shout in the comments box.

Sunday, April 8, 2012

How To: Implement In App Purchase The Easy Way, Ever.

There are plenty of IAP (In App Purchase) tutorials in the internet. BUT, all of them are damn complicated. None of the tutorials (that I found anyway) that shows the easiest way to implement IAP. If that is how you feel, read on....

For example, over at Ray Wenderlich (this tutorial), you can try read it, unless you are very familiar with classes and what nots, you'd end up like me - giving up to make IAP in your app. Don't get me wrong, Ray Wenderlich provides one of the TOP NOTCH tuts, but sometimes they just speak a different language than us, noobies and amateur coders.

So I thought, since it is my first time to implement IAP in one of my apps, (I never had an IAP app before), might as well I try find my own way of putting an IAP which is EASY, STRAIGHTFORWARD, and FAST TO IMPLEMENT.



Lets get started.

Firstly, for this tutorial, I am going to assume a few things:

1. that you want to implement IAP by way of "feature" buttons.
2. that you do not have too many items to be purchased (if you do have many IAP items,
then it is probably best to use UITableView as in Ray Wenderlich's sample)
3. that all IAP items/features are built in into your app bundle (ie, you do not have a downloadable IAP items, etc)

If these assumptions are what you are doing, then read on! For this tutorial example project, I'll just put 2 buttons on a single view app. One button is an example of a readily available feature and another button is another feature that requires an IAP to use.

So, as normal, go to your XCode, create a project and goto the XIB file and put 2 buttons on it. For the 2nd button, you need to put an "indicator" that the feature is kinda locked. Here, I use a padlock icon as the background image to illustrate this. If you use button of the type Custom, then you could set the button's Image property as the padlock icon and the background property as your button appearance. When the app is ran, here's what it looks like:

I also added a UILabel at the bottom just to do something when you press the feature button. For this example, I am going to make the label say "Feature 1" when you press button 1 and say "Feature 2" when you press button 2.

But since Feature 2 is a IAP item, we need to check if user has purchased the feature before showing "Feature 2". Anyway, lets make the basic functions first.

Declare 2 IBActions for the 2 buttons. And also declare IBOutlets for the IAP Feature button and for the UILabel in .h. Also declare a UIAlertView so that we can check for the user response in this alert later. Remember to synthesize both objects in your .m file.

Your .h should look something like this:


#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface ViewController : UIViewController {
    IBOutlet UIButton *feature2Btn;
    IBOutlet UILabel *featureLabel;
    UIAlertView *askToPurchase;
}

@property (nonatomic, retain)  UIButton *feature2Btn;
@property (nonatomic, retain)  UILabel *featureLabel;

-(IBAction)doFeature1:(id)sender;
-(IBAction)doFeature2:(id)sender;


@end

 Now open XIB file and connect all the necessary links. Connect IBActions to Touch Up Inside of File Owner, and both IBOutlets. Note that we need IBOutlet of Feature 2 button because we are going to change the Lock icon condition later on. Having the button declared will make things easier later.

Next, open .m file and write the methods for the button taps.


 
-(IBAction)doFeature1:(id)sender {

    featureLabel.text = @"Feature 1";

}

-(IBAction)doFeature2:(id)sender {

    featureLabel.text = @"Feature 2";

}

Now run the app, both buttons should be working now when you tap it, the UILabel below will change according to which button you tap! Congratulations. No, you are not done. We want to lock Feature 2 now, so tapping button "2" should check for IAP first before allowing user to use it.

For this purpose, we will create another method to check for IAP item somewhere.... Earlier, when I was learning how to implement IAP, I thought of using NSUserDefaultsto store some values (like a BOOL) so that we can set that flag if user completed an IAP. However, there is a problem with this, while it is simple, if user deleted the app, and redownload it later, the IAP flag will be gone forever - NSUserDefaults is stored as .plist file in the APP BUNDLE folder.... means user who already bought the IAP, needs to purchase the IAP again = angry users. Grr..

A better way to handle this is to make use of the KEYCHAIN. Now, we can learn to implement Keychain, but why reinvent the wheel? Head over HERE to download the KeyChain wrapper. After you downloaded it copy and include both SFHFKeychainUtils.h and .m into your project. (I've already included the files in the Sample project of this tutorial, but do download the latest version for your app).

What is Keychain?Keychain is something like Registry in Windows. It is a more secure place to store sensitive information in the iDevice and it is not tied to the app bundle. 

In your .m file, remember to #import  "SFHFKeychainUtils.h". We also need to add the "Security.framework" to our project. After that, lets create the method to check the IAP item in the keychain.



-(BOOL)IAPItemPurchased {

      

    NSError *error = nil;

    NSString *password = [SFHFKeychainUtils getPasswordForUsername:@"IAPNoob01" andServiceName:kStoredData error:&error];

   

    if ([password isEqualToString:@"whatever"]) return YES; else return NO;

   

}
We are just simply using the username/password saving feature of KeyChain utility to save our IAP item data. Nothing fancy. Also notice we are declaring this function as a BOOL, so it returns a YES or NO immediately when we call for it. Note that all 3 data here: username, password and ServiceName are developer defined. You choose what you want for those keys (they are all NSStrings). It does not matter what they are, as long as we can check for the "password".

Now, lets implement the lock feature of Feature 2. Modify the doFeature2 method as below:

-(IBAction)doFeature2:(id)sender {

   

    if ([self IAPItemPurchased]) {

   

        featureLabel.text = @"Feature 2";

    } else {

        // not purchased so show a view to prompt for purchase

        askToPurchase = [[UIAlertView alloc]

                            initWithTitle:@"Feature 2 Locked"

                            message:@"Purchase Feature 2?"

                            delegate:self

                            cancelButtonTitle:nil

                            otherButtonTitles:@"Yes", @"No", nil];

        askToPurchase.delegate = self;

        [askToPurchase show];

        [askToPurchase release];

    }

}

What we do here is check if the IAP item flag is available in the keychain, if it exist then user has purchased Feature 2 before, so we proceed with it's function. If not, prompt user to buy Feature 2. In this example, I just use a simple AlertView. You can code a pretty UIView with colorful images and so on - entirely up to you.

Now lets handle the alertview feedbacks. If user chose to purchase, then we start the IAP request.
Before we go on to that, lets create an IAP item in iTunesConnect first.

Creating/Registering IAP Items in iTunesConnect.
 Logon to your iTC account and click Manage Applications. Then click your app icon, and at the top right hand corner, click "Manage In-App Purchases". On the top left side, there is a Create New button. Click it. Click on Non Consumable. (Non consumable is a purchase type where user only needs to pay for a feature just one time.) Key In Ref Names and other details as shown in the pic below:



As for the screenshot, just upload a Dummy image of size 960x640 and you'll be able to save the IAP item. But you have to remember to update this screenshot prior to submission. The key info in this form is the Product ID. In this case com.emirbytes.IAPNoob.01 , this is what we will be calling from our app later. Once we are done we can then create Test Accounts to test the IAP later. In the main page of iTunesConnect, go to Manage Users, and click on Test User and add a test user. Once you are done, you can logoff and return to coding.

Implementing StoreKit
The API that will help us implement the IAP is called StoreKit. So obviously we need to add the StoreKit.framework to our project. Next we need to import StoreKit.h and implement the related delegates, so modify the .h file as below:



#import <UIKit/UIKit.h>

#import <StoreKit/StoreKit.h>

@interface ViewController : UIViewController <SKProductsRequestDelegate, SKPaymentTransactionObserver> {

    IBOutlet UIButton *feature2Btn;

    IBOutlet UILabel *featureLabel;

    UIAlertView *askToPurchase;
}

@property (nonatomic, retain)  UIButton *feature2Btn;

@property (nonatomic, retain)  UILabel *featureLabel;

-(IBAction)doFeature1:(id)sender;

-(IBAction)doFeature2:(id)sender;

@end

Since we use AlertView to prompt the user, we need to input the AlertView delegate as well, so add the UIAlertViewDelegate in .h file and implement the delegate function as below:



-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {



    if (alertView==askToPurchase) {

        if (buttonIndex==0) {

            // user tapped YES, but we need to check if IAP is enabled or not.

            if ([SKPaymentQueue canMakePayments]) {

               

                SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"com.emirbytes.IAPNoob.01"]]; 

               

                request.delegate = self; 

                [request start]; 

               

               

            } else {

                UIAlertView *tmp = [[UIAlertView alloc]

                                    initWithTitle:@"Prohibited"

                                    message:@"Parental Control is enabled, cannot make a purchase!"

                                    delegate:self

                                    cancelButtonTitle:nil

                                    otherButtonTitles:@"Ok", nil];

                [tmp show];

                [tmp release];

            }

        }

    }

   

}

 First we check if the alertview is the IAP prompt alertview, if it is then we check if Yes button was pressed, and if it is, then we check "canMakePayments". This function will return YES or NO depending on whether the In-App Purchases Settings in the device is set to On or Off (Settings App -> General -> Restrictions). This way, the payment is allowable only if this restriction is not set (to prevent childrens from simply buying your IAPs unintentionally). And, if we can make IAP request, initiate the request with the Product ID that we specified earlier in iTC.

Since IAP requires internet connection and takes some time (a few seconds) to be processed, at this point it is a good idea to check for internet connection availability and to display a Wait View (I do not include it for the sake of simplicity). For easier demo, I put another UILabel to show the status of purchase.

Once we request this IAP to the IAP server, the app will then wait for a reply from the IAP server and fires off the StoreKit delegates:


-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {    

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response  

-(void)requestDidFinish:(SKRequest *)request

-(void)request:(SKRequest *)request didFailWithError:(NSError *)error  

The important delegates are the first two that are in bold.  Right after we request a product via SKProductRequest in alertView delegate above, the first delegate that is going to respond is the didReceiveResponse delegate. Here, it will check whether the Product ID we requested is available or not, and if available, do the payment (Ka Ching!)...


 -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response 

{ 

   

    // remove wait view here

   

    SKProduct *validProduct = nil;

    int count = [response.products count];

   

    if (count>0) {

        validProduct = [response.products objectAtIndex:0];

       

        SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.emirbytes.IAPNoob.01"];

        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

       
[[SKPaymentQueue defaultQueue] addPayment:payment]; // <-- KA CHING!

       

       

    } else {

        UIAlertView *tmp = [[UIAlertView alloc]

                            initWithTitle:@"Not Available"

                            message:@"No products to purchase"

                            delegate:self

                            cancelButtonTitle:nil

                            otherButtonTitles:@"Ok", nil];

        [tmp show];

        [tmp release];

    }

   

   

}  

After we request a payment, the next delegate that is going to respond is the updatedTransactions delegate, where we check for transactions type: there are 4 types that must be handled properly.


SKPaymentTransactionStatePurchasing - indicates still processing the purchasing - display a wait view.

SKPaymentTransactionStatePurchased - indicates purchase completed - unlock features by code

SKPaymentTransactionStateRestored - purchase restored from an interrupt (phone call etc)

SKPaymentTransactionStateFailed - purchase failed - show alert

I will explain the code in StatePurchased condition:

 
case SKPaymentTransactionStatePurchased:

           

                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                // remove wait view and unlock feature 2

               

                UIAlertView *tmp = [[UIAlertView alloc]

                                    initWithTitle:@"Complete"

                                    message:@"You have unlocked Feature 2!"

                                    delegate:self

                                    cancelButtonTitle:nil

                                    otherButtonTitles:@"Ok", nil];

                [tmp show];

                [tmp release];

               

               

                NSError *error = nil;

                [SFHFKeychainUtils storeUsername:@"IAPNoob01" andPassword:@"whatever" forServiceName:kStoredData updateExisting:YES error:&error];

               

                // apply purchase action  - hide lock overlay and

                [feature2Btn setBackgroundImage:nil forState:UIControlStateNormal];

                // do other thing to enable the features

               

                break;


First, in above case, we tell the server to finish the transaction, then we show to user that the Feature has been unlocked. Then, we register a flag in Keychain with the specific username, password and servicename (remember they are case sensitive). Finally we remove any Padlock icon and other visual settings.

IMPORTANT: YOU CAN ONLY TEST IN-APP PURCHASE IN YOUR DEVICE, AND NOT IN SIMULATOR. USE THE DEVELOPMENT PROVISION TO TEST IT. AND MAKE SURE YOU LOG OFF YOUR OWN APPLE ID and USE THE TEST USER ID TO DO TEST THE IAP IN SANDBOX ENVIRONMENT! see additional notes.
We are almost done. Finally we need to re-check the purchase in the Keychain everytime the user activate the app. In this case I put it in viewDidLoad - here we call the checking function we created earlier - see how it is useful to have?:


 
 if ([self IAPItemPurchased]) {

        [feature2Btn setBackgroundImage:nil forState:UIControlStateNormal];

    } else {

        [feature2Btn setBackgroundImage:[UIImage imageNamed:@"Locked.png"] forState:UIControlStateNormal];

    }

Here are some screenshots sequence of the IAP in action:







____________________________________

Oops! I forgot one more thing!

Since you will be testing this in your device, you might want to test the IAP a few times. So we need to add another button (which will be hidden or just deleted when you submit the app) to reset the Keychain value.

Just add a button... and implement IBAction for it as below:



-(IBAction)deleteKeyChain:(id)sender {

    NSError *error = nil;

    [SFHFKeychainUtils deleteItemForUsername:@"IAPNoob01" andServiceName:kStoredData error:&error];

}


To test the IAP process again, just tap the button and delete the app in your device, and then rerun it. The app's Feature 2 should be Locked again.

Ok, now we're Done! Yay!


ADDITIONAL NOTES:

Some readers have given me some feedback about how they get a "No Products" alert when running it on the device. Please check that you have assigned Code Signing to the certificates correctly (both development and Release provision profiles). Things you can try:

Reset your app - delete the app in sim, do Clean All in XCode, double check your provisioning profiles (reinstall them if necessary). Remember that bundle ID are case sensitive. Ensure to logout your iTunes Store account in Sim/Device and make sure you login with a test account to test the IAP. Check everything in detail.

Also, I have verified that you can test the IAP in Simulator as well (I tested it using XCode 4.3.1 and Simulator 5.1). Thanks all for your feedbacks!

Thursday, March 22, 2012

How To: Prepare App For Submission and Submit To AppStore In 10 Steps

App completed. So now what?

The Apple documentation will help you a lot in preparing and submitting the app to the App Store. But, as I have experienced it myself long time ago, it could be a confusing and unclear steps to do this because there are no pictures to guide you through it and, some of the terms maybe totally new to some of you, noobs.

So, this tutorial will hopefully help you to submit an app to the appstore using XCode 4.3.1.

1. After you completed your app, tested it in the simulators, the first thing you need is app icons. Create 6 app icons as follows in your image editor (MAKE SURE THEY ARE NAMED EXACTLY AS BELOW - Their names are case sensitive! icon.png and icon.PNG and Icon.png are all different!)

1. Icon.png - 57 x 57 pixels
2. Icon-Small.png - 29 x 29 pixels
3. Icon@2x.png - 114 x 114 pixels
4. Icon-Small@2x.png - 58 x 58 pixels
5. Icon-72.png - 72 x 72 pixels (for iPad) - optional
6. Icon-Small-50.png - 50 x 50 pixels (for iPad) - optional

Once you are done, copy these icons into your project folder and drag and drop them to your Projects' Resources Folder to include them in your project.


 Then open the project's plist file (App-Info.plist, or info.plist) and add a row of "Icon files" (right click and select Add Row), then type Icon files in the field. Press return and you will see the line becoming an expandable list. Click on the triangle to expand it and then you can start adding the Items and icon file names such as below:


2. Next make sure you have included the "Loading" image called Default.png and Default@2x.png into your project. You do not need to specify these anywhere because the SDK will recognize them through their names. The loading image is the image that shows at the beginning of an app execution.


3. Next choose your own custom Bundle Identifier. What the heck is a bundle identifier? Exactly my question when I was trying to submit my first app too! LOL

A bundle identifier is basically some sort of signature of your application binary. It can be any kind of string. But typically, it is of the type com.yourcompany.yourappname. For example, if your app is a flashlight app named myFlash, and your name is David Beckham, your Bundle identifier could be com.beckham.myflash. For another example, Apple's bundle ID is com.apple.iphoto for the iPhoto app. So now you get what a Bundle Identifier is, go on and open your app-info.plist again and enter your bundle identifier in the Bundle Identifier row.

4. Next is to put a version number to your app. Normally, you can put 1.0. Some people use 1.0.0. Some people even just have 1. It is entirely up to you how to do the numbering for the version as long as it is easily manageable to you. Again, to enter version number, open up app-info.plist again and enter it for both  "Bundle versions string, short" and "Bundle version". If any one of these do not exist, add them manually by right clicking and choosing Add Row, and type it in. XCode has an auto complete feature that surely will help you to key in the correct name for it. For my case, I put my app version 2.0 because I was doing an update.


5. At this point your app is just half way from submitting to app store. Next we need to go to the developer's portal and
a) create an App ID and assign Bundle Identifier to it,
b) create Development Provisioning Profile, (so you can test your app in your device) and
c) create Distribution Provisioning Profile (so you can submit your binary to appstore).

By this time, you should know that there are 2 MAIN WEB TOOLS for Developers that Apple provides: 1) iTunesConnect. 2) Apple Developer Portal. 

To create an App ID, you need to enter the Apple Developer Portal (http://developer.apple.com). Then choose iOS. From there, you have to login using the same username and password as your iTunesconnect webtool. This tutorial concentrates on the XCode side, so I'll just briefly explain how to do the above a), b) and c).

a) To create an App ID, once you are logged on to Developer Portal, click the iOS Provisioning Portal link. In the left column, there are Home, Certificates, Devices, App ID, Provisioning, Distribution. To create App ID, click App ID link. At the right top side, there is a button App ID. Click on that and fill in all the necessary info in the form. 

Description: enter whatever name you want for your app ID. This is what will appear in your XCode later. I normally use "<AppName> AppID".

Bundle Seed ID: just leave it as it is. (Default is Use Team ID)

Bundle Identifier: type the identifier you chose in step 3 above. After that just click Submit. Now your app ID is ready.

b) To create Development Provisioning Profile, now in the same page, click "Provisioning" link on the left column. In here, you will see a few tabs, Development, Distribution , History, and How To. Note that How To contains a very good info with detailed step by step on how to do provisioning. In fact, each of the sections (Certificates, Devices, App ID, Provisioning and Distribution) has a How To tab. So if you are stuck, read the info in there. 

Under Development tab, click New Profile. Then enter the info in the form.

Profile Name: Enter a name (something like the app ID description). I normally enter "<AppName> Dev" to make it clear that the profile is a development profile so I can select the correct profile in XCode later on.

Certificates: Tick your company certificate. (If you don't tick, your provision will not be able to sign)

App ID: Select the app id you just created in step a.

Devices: Tick the device you want this profile to link to (i.e only devices you tick will be able to run your app during development and testing). (Adding Devices tutorial is not included here, but you can easily add it by clicking the Devices link and follow the info in How To tab.

Then click Submit and wait for a while and REFRESH the window and you'd be able to download the profile into your mac (Click on the button Download on the right side of the Provision list).

c) To create Distribution Provisioning Profile is EXACTLY the same steps as b) except that you do not need to choose the Devices (the devices options should be disabled).

Once you have created all the necessary provisions (normally just these 2 profiles = 2 files), 2 files should be already downloaded to your mac. To install, just drag and drop them onto your XCode icon in Dock. The Organizer will automatically opened and your profiles should be listed there.

6. Next is for you to choose a product name for your binary. Product name will appear in the user's device right under your app's icon. There is a limit as to how long the name can be, because if it is too long, then it will show as "MyApp...ion". Something like that. So choose the name carefully, and you can test it in your simulator. To input a Product name to your app, select your Project in the left pane of XCode and select the Build Settings of the TARGET in the right pane as shown below. Make sure you select All button and Levels button under Build Settings:


Then, In the search box, type "Product Name" and return. An entry will be shown, so you just enter your app name in there. Here is an example of my app called Everlight. 

7. In the latest XCode, we need to add Architecture info correctly otherwise iPod Touch or older iPhone will not be able to run your app. While in the same page of XCode as in step 6, Search for Architectures (or you can just scroll up to find the Architectures entry. Click on the up-down arrow and select Others...
A window will pop up. Here $(ARCH_STANDARD_32_BIT) means armv7 (i.e the chip that iPhone4 and 4S uses). However iPhone, iPhone 3G, 3GS and iPod all uses armv6. So you need to add it by clicking the + button at the bottom and key in armv6. The order which is first is not important.

8. Now scroll a bit down, and find Code Signing entry. Here you must select the proper profiles. Make sure you select for ALL EIGHT entries like in the screenshot below.

Every single entry should be in BOLD indicating they are correctly selected. If any one of it is not in BOLD, you can try select "Don't Code Sign" for all EIGHT ENTRIES, and then select your profile again for all eight entries. Here is where your Profile Name is useful because when you click the up/down icon on the right of each entry, a list will pop up with all of your available profiles. For Debug row, choose your Development Profile. And for the Release row, choose your Distribution Profile. We are almost done!

9. Next, Click the Summary page of your project's Target as screenshot below:


Here you can verify your Bundle Identifier. Make sure they are matched case per case to the Bundle Identifier you chose earlier. Bundle Identifiers are case sensitive. Here you can also see your Version number. For Devices, select iPhone, unless you just made a universal app or an only iPad app.

Deployment Target  - This is a very important settings. Deployment Target indicates what is the minimum iOS version that a user needs to run your app. A common practice is to allow a support to the lowest possible version, for example, iOS3.2. or 4.0. If you set to 4.0, a user with version 3.2, will not be able to download/buy your app. But a user with iOS4.0, 4.1, 4.3, 5.0 and above will be able to do so.

Supported Device Orientations - Select which orientations that your app support.

App Icons: Should show you your icons properly. And Prerendered option is if you do not want that gloss effect to be added to your icon.

Launch Images: Default.png and Default@2x.png should appear here. If not check back your file name properly.

10. Now you're ready to Submit to App Store. Well, not just yet. You need to add a new application in iTunesConnect Dashboard first! Logon to iTunesConnect and goto Manage Applications and click Add New App button on the top left. Next select the Default Language (English normally for me), and key in your the following:

App Name: App name must be unique, and not a duplicate of those already existed in AppStore. 
App name cannot be changed once your app is approved so choose carefully. However you can change the app name at an app update later on.

SKU Number: This is for your own personal use in the Sales report that Apple will produce. For example, my photo app SKU is called PH-0001. You must decide this for yourself because you will be using the SKU to identify your app in the Sales Report.

Bundle Identifier: You should know this by now. If not, read back from start of this tutorial :P

Click Next and enter the following info:

Availability Date: Don't change it if you want it to be available right after it has been approved.

Price Tier: Select a Price for your app. Tier 1 is 99cents. Tier 2 is 1.99 cents and so on. After you select the Tier, you'd be able to see in a table how much does the Tier represent (if not, click View Pricing Matrix)

Discount For Educational Institution: Tick this if you want educational institution (like university or school) to be able to bulk purchase your app at a 50% discount. For example if your app is 99cent, then if the school purchased 100 copies of your app, they'd just pay $49.50, which is a motivation for them to bulk purchase more.

Click Next, then you can enter your typical app data: Version Number, copyright, Primary and Secondary Categories, App Rating, MetaData, iTunes Artwork Icon and Screenshots. I'm sure you are already familiar with this. But a little important notes:

1. Enter the version number correctly. If the version number entered here does not match to the one entered in XCode, you won't be able to upload your app. 
2. If you haven't prepared Metadata, iTunes Artwork Icon and Screenshots, you can just prepare a "Dummy" images first (iTunes Artwork Icon = size 512x512px , 1 dummy screenshot of 960x640) and upload them, and just type some dummy words in the Description section (like "will add later") at this point because otherwise you won't be able to finish adding a new app data to iTunesConnect!

Finally Click Save and your app data in iTunesConnect is ready and you can now upload your app via XCode. Go back to XCode, open your project , go to XCode menu Product -> Archive.


When you click Archive, Organizer will be fired again showing archives of apps. Select your app name and click Validate. You will need to login with your iTunesConnect account and XCode will analyze your binary for any possible errors or missed items. Once validation is a success, XCode will tell you and you can submit by clicking the Distribute.. button and select "Distribute to AppStore". The similar process will happen again and just wait for the upload to finish.

DONE!

Easy steps? Not really. Worth it? DEFINITELY!

GOOD LUCK!

Wednesday, February 22, 2012

The Art to Make Your iPhone App Shine!

This is not a coding tutorial, but nonetheless very important aspect of iPhone app design.

There is a lot more to making an iPhone app than just making a software that functions. For your app to shine, you need to consider a few features that are essential to a good app. As an app developer, you need to think differently than a software developer. An app developer develops and create software that has the nearest human interactions to a user. Our aim, should be, therefore to make a an app that simulates a pet. A pet owner loves his pet, caresses it, loves it, brings it to the bed. That's what you should aim your app should be, and in order to create something like that, consider the following:

1. Sound effects. Many apps out there do not really need sound effects. But sound effects add interaction values to the users. For example, take the Twitter app, it does not NEED sound, but it has some sound like when you drag down the list to update. (It emulates a pet barking or meowing to the owner)

2. Gestures. Do not rely 100% on button taps if you can. Use gestures - pinch, swipe, drag, shake, turn, twirl. (These actions relate to caressing a pet).

3. Help information. Many apps do not have this. Even when they have it, it is too obscured on how to get it. Help info includes how to use the app, explanation of how to use a certain feature that is not so obvious, and so on. Sure, you wrote about it in the app description, but when the user is done downloading your app, do you really expect him/her to return to your app page? No!

4. Animations. Spend a little time to code nice animations. Don't just make things appear out of nowhere. Make it SLIDE, make it FADE, make it DISSOLVE, etc. (These relates to a pet doing tricks for the owner).

5. Polished Graphics. Would you buy an ugly dog or cat as a pet. There you go. Firstly, Apple and Superb Graphics rhymes. So, polish your graphics again, and again, and again. 

Well, that's 5 very important aspect of iPhone design. Remember them when you are designing an iPhone app. Good luck.


Tuesday, February 14, 2012

How To: Find for a Function/Method That You Did Not Know Existed?

This is a simple but VERY USEFUL tip for new developers who often want to know what other function is available for a particular object. The hard way is to go through Apple's Documentation and read for each Objects.

The easy way is through your XCode code editor. Let me show you how:

Say, you are wondering (or forgetting and trying to remember) what was the code to write variable into the NSUserDefaults (sandbox of your app).

Normally, XCode 4 will automatically pop up the code completion, but if it is not, then you can press ESC button on your keyboard and it will pop it up for you.


Once this is popped up, you can scroll through the valid functions that starts with "set" because we typed that already.

Even if you haven't type anything, just go ahead and press ESC and all possible functions to be input at the cursor point will be popped up for you. 


But surely, the options listed are a whole lot more to choose from. It is a very helpful feature of XCode which every devs should know.

Tuesday, February 7, 2012

How To: Create Horizontal UIPickerView (Custom)

It's been a while since I last wrote any real tutorial. I wanted to write this tutorial for a while, but was delayed due to updating my own apps, and creating new apps, and also due to relatives who got seriously ill, yadda yadaa, whoop dee doo whoop dee dye and so forth.



Anyway, today I'd like to show you how you can create a custom sized horizontal UIPickerView. UIPickerView is an awesome object to display a list of items. While you can accomplish this using UIScrollView easily, the behaviour of UIPickerView is slightly better because the items in UIPickerView is auto selected when user chooses it - that cool spring effect centers the selection nicely at as well.



So lets get started, first of all, all you need to do is drop a UIPickerView object on your view in the Interface Builder. Then in your .h file input:


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIPickerViewDelegate> {

    IBOutlet UIPickerView *pickerView;

    NSMutableArray *itemArray;

}

@property (nonatomic, retain)  UIPickerView *pickerView;

@end

Basically we're just declaring our UIPickerView as IBOutlet (nothing new in declaration method here). We also added a NSMutableArray so that we can manipulate our items and be able to add our items in the pickerview easily later. We also add UIPickerViewDelegate at the interface because we will be using the built in Delegate functions of UIPickerView object.

Hang on a minute, what the heck is an NSMutableArray? If you are familiar with some basic programming I am sure that you are familiar with an array. An array is a defined quantity of collection of data. For eg:

myFish[14] holds 15 variables. from 0 to 14. (Remember index of an arrays always start with 0).
So you can access them by myFish[0] = Tetras; myFish[1] = Rasboras. And so on. But you are limited to 15 fishes. This is where NSMutableArray differs, an NSMutableArray is an array that is mutable, or expandable/changeable. So if you declare myFish as an NSMutableArray, then you can have up to whatever value you wish, so long as you be careful not to overload it (memory issues).

Back to the tutorial:

So now you have declared the UIPickerView, go to Interface Builder and connect BOTH the "delegate" and "Referencing Outlet" to the FileOwner.

Next, we go to .m file and synthesize the UIPickerView. Also we'd want to add the UIPickerView delegate methods as below (read the comments for each delegate's purposes:


- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {

return 1;

}

- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {

return [itemArray count];

}


- (UIView *)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view

{

return [itemArray objectAtIndex: row];

}

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {



}


numberOfComponentsInPickerView
This delegate is easy to implement, just type "return #;" where # is the number of components
you want. "Component" is the scrollable object in a pickerview. For example, a date pickerview has 3 components where user can select each of date, month and year. For our case, we are going to use just 1 component.

numberOfRowsInComponent
This delegate you need to return the number of items in each component. If you have multiple components,
you need to use switch (or if) statement to specify for each components. In our case we just have 1 component, so we only return the item count of our array.

viewForRow
This delegate is where you specify the "VIEW"/"Object" of the item. Since we store our items in
array, we just need to return the object by using: [itemArray objectAtIndex:row];

didSelectRow
This delegate is always called when user selects an item. Write the actions you'd like to happen when user select something in here.

Remember that delegate functions must be written as it is, EXACTLY. Any deviation might cause it not to work. Do check Apple docs for the latest delegate function names in case your implementation does not work.

Next is the fun part, customizing the UIPickerView. We will add the customization code in the viewDidLoad as we want it to be customized after the view is loaded. Write the codes below in the viewDidLoad.

// set the pickerview delegate to itself. This is important because if you don't set

// this, then the delegate functions will not work/be called.

 self.pickerView.delegate = self;

// here is where the customization lies: CGAffineTransform is a way to transform

// object according to scale and rotation. Here we rotate the pickerview by PI/2

// which is 90 degrees in radians. Then we concat the rotation transform with

// scale transform, and finally setting the pickerview transform.

CGAffineTransform rotate = CGAffineTransformMakeRotation(3.14/2);

 rotate = CGAffineTransformScale(rotate, 0.1, 0.8);

 [self.pickerView setTransform:rotate]; 

// set the center location.

 self.pickerView.center = CGPointMake(160,75);

  // Here I decided to add UILabel as the item's "object"

// you can use ANYTHING here, like UIImageViews or any class of UIView

// Since we rotate the pickerview in one direction, we need to compensate

// the item's angle by counter rotating it in the opposite direction,

// and adjust the scale as well. You may need to try a few times to get

// the right/suitable size as for the scale.

 UILabel *theview[20];

 CGAffineTransform rotateItem = CGAffineTransformMakeRotation(-3.14/2);

 rotateItem = CGAffineTransformScale(rotateItem, 1, 10);

 // next alloc and create the views in a loop. here I decided to have 20

// UIlabels, each with a text of 1 to 20. Set the other UIlabel's property as you wish.

 for (int i=1;i<=20;i++) { 

  theview[i] = [[UILabel alloc] init];

  theview[i].text = [NSString stringWithFormat:@"%d",i];

  theview[i].textColor = [UIColor blackColor];

  theview[i].frame = CGRectMake(0,0, 100, 100);

  theview[i].backgroundColor = [UIColor clearColor];

  theview[i].textAlignment = UITextAlignmentCenter;

  theview[i].shadowColor = [UIColor whiteColor];

  theview[i].shadowOffset = CGSizeMake(-1,-1);

  theview[i].adjustsFontSizeToFitWidth = YES;

    UIFont *myFont = [UIFont fontWithName:@"Georgia" size:15];

  [theview[i] setFont:myFont];

    theview[i].transform = rotateItem;

 }

    

    // then we initialize and create our NSMutableArray, and add all 20 UIlabel views

// that we just created above into the array using "addObject" method.

   itemArray = [[NSMutableArray alloc] init];

  for (int j=1;j<=20;j++) {

       

        [itemArray addObject:theview[j]];

   }

That is all there is to it. Run your app and it should display a nice horizontal UIPickerView!
How about have it do something when you select an item? Easy. Go back to .h and add another IBOutlet of UILabel *myLabel. Go to your XIB file in IB and add a label and connect the Outlet to FileOwner as myLabel. Goto .m file and synthesize myLabel. Then goto UIPickerView delegate called didSelectRow and add the following line:
myLabel.text = [NSString stringWithFormat:@"SELECTED: %d", row+1];
Now when you select a row, the label will show you which row you selected. Cool eh?
Well, that's it for now. Hope this tutorial helped someone. Good luck!

Wednesday, October 19, 2011

Coding - Flow Like a River

I thought I write about how newbies tend to copy and paste codes to make things work. I admit copy and paste is the easy way to learn coding. I do it at times as well. But in the end, programming/coding is about how an app FLOW. The flow of an app is very crucial for every newbie developer to grasp.

Often I read programming forums there are people who post codes and asking why it does not work. And you know immediately that they are just copying blindly since they don't even know what each line does and how the code flows in the app.

Every app, or programs, or executables, (whatever you want to call them), have a flow of executions. It is like reading a book, you read the title, first paragraph, next paragraph, page 1, page 2.. and so on. iPhone apps are no different. In an iPhone app, you have the main.h (yes we ignore that file and some don't even know it exists!) which calls the AppDelegate, and the AppDelegate calls the ViewController. To simplify, lets skip direct to the AppDelegate.

THE FLOW of an iPHONE APP

1. AppDelegates is called - applicationDidFinishLaunching is executed. In this method normally we directly call the first viewController (say FirstViewController) to appear after the Launch image is shown.

2. Next thing that happens, of course, is the codes inside the function "viewDidLoad" in FirstViewController.m.
Normally in this method you can put initialization of the view (for eg, buttons location, hidden/not, start a timer and so on)

3. Then from here, everything is based on user's input (or timer's action if there is a timer).

4. App Exit / Goes to background.

This is a simple flow, but many people do not realize this. Even in each of the user's actions there are flow of their own. You, as developer need to cater for every single line of codes. If you want to use a variable, you must check what is the contents of that variable. Has it been loaded with values? Has it been initialized even?
There is no point to read a variable into a UILabel, if you haven't loaded any values in it!

For eg,

in .h
NSString *myStr;


in.m (IBAction)userPressButton

myLabel.text = myStr;


This won't work. You need to load/init the myStr with something first (for eg, in the viewDidLoad!)

in .m (void)viewDidLoad

myStr = [NSString stringWithFormat:@"%@",[ [NSUserDefaults standardUserDefaults] objectForKey:@"storedString"]];

Then when user press the button, myLabel.text will show a value and it works.

These are the FLOW of apps, and of functions/methods and all developers should know how a user use their apps and what to do if a user acted.

I hope this post has been useful.

Tuesday, July 19, 2011

Kinda-Tutorial: Where to Find Free Sounds For Your App/Games

Being an indie developer, it is tough to gather a good sound pack for an app or game. You can hire a sound artist, and some of them do offer real cheap. For me it is a problem, because I do not have PayPal account. If a sound artist were to offer me for him to create a whole sound effects (of about 20 short sounds + 2-3 short music loops) for a simple game for USD50, I'd definitely buy it. But without PayPal account, it is hard to do so.

So, today I am going to share with you how I get my sounds done. For free. And Legally!

Generate Your Own Sounds!
You guessed it. The cheapest method is to generate your own sounds. There are many sound fx producer. But the one I use is a royalty free sound creator called - cFXR. Google it up. In my opinion, cFXR is a SUPERB sound producer. I particularly love the "Random" mode.

Another way to generate your own sounds is - record them! I have recorded some of my own voice and other sounds (like "pop", click etc) and edited them in Audacity. Audacity is also a great royalty free sound editor. You can trim the sound clip. You can also apply effects to them, like Echo, or make it sound like its coming from a walkie talkie, and so on.

Get Royalty Free Sounds From Other Creative People
I have so far, found 3 SUPER GREAT website that offer royalty-free (with Attribution) sounds.

1. www.freesound.org
This site concentrates mostly on sound effects, and not so much musics.

2. www.ccMixter.org
This site has a lot more variety on musics. For ccMixter sounds, be sure to read the author's note on how to use their work. As I understand, not all are free to use commercially. So be careful.

3. YOUTUBE!
I just found another source of good royalty free sounds. At Youtube.com! Just search for "<something>
sound effects" and you will get some. Be sure to copy those sounds where the author allows a free commercial use. Use any free online youtube-to-wav or youtube-to-mp3 services to extract the audio from the vids. Then, as normal, edit them in Audacity.

There you go.
Hope that helps.

Wednesday, May 4, 2011

How To: Have Cool Backgrounds From Code

iOS stocks some built in backgrounds images ready to be used by any objects that has a UIColor property. Ever wonder how to get them? One way is to capture the screen when it is showing on the iphone (by pressing home + power button simultaneously), copy the pattern and fill an image with it as your own custom.png background image. But wait, there is a much simpler, easier way.

This blog post is a simple and straightforward tutorial, therefore no downloadable sample code.

Try to create a View based project and add the following code at viewDidLoad.
 self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
//self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
//self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];

These will give your view a standard Apple's OS backgrounds image texture that we always see.
So you do not need to make it your own, wasting resources.

For your reference, here is what each "color" give:

viewFlipsideBackgroundColor

scrollViewTexturedBackgroundColor

groupTableViewBackgroundColor

Cool eh?

Wednesday, April 27, 2011

Comparing Variables

I have seen quite a lot of people asking some basic questions about comparing integers, floats, strings, and so on. Many made mistakes in doing so. Such mistakes are:

float x = 0.1;

if (x==0.1) {

// do something

}

This won't work, because a float is what it is.. a number that "floats". A 0.1 is not precisely a 0.1.  In the case of above, x being set to 0.1, but it may hold a value of 0.1000000001 or -0.100000002341 and so on.

So the correct way to compare a float is to set a range.
float x = 0.1;

if ((x<=0.10005)&&(x>=0.00005)) {

// do something

}

There is another variable comparison mistakes that people often do, and asked why it does not work and that is comparing NSString.

NSString *myStr = @"My House";

if (result==myStr) {

// do something

}

This, too, will not work because an NSString is a pointer. A pointer is like an address to your home. Your house needs a renovation, but you are trying to renovate the address. Which is absurd.

There are often a simple function to compare string objects, an in XCode, it is called isEqualToString:

Thus, the correct way to do it is:
NSString *myStr = @"My House";

if ([result isEqualToString:myStr]) {

// do something

}

You can interchange result and myStr in that syntax, no problem. I hope this simple tutorial post helps noobies to understand the variables and how to compare them the correct way. As this tutorial is a simple one, there are no downloadable source codes.