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.

Wednesday, March 9, 2011

How To Do: Slide to Unlock


This is a simple tutorial  to create "slide to unlock" feature.  As you may have guessed, we have to use UISlider. UISlider is an awesome object for many purposes - adjusting parameters of an object, or values of anything (size, amount, etc). But this time we will use it as a "Unlock Key". This type of control is useful when you have an app doing something and the user then puts the iPhone in his pocket while the app is still running. If we just use a normal UIButton to unlock, the user could accidentally touched it while the phone is in the pocket, and unlocked the screen of the app, accidentally. This is the same application as the normal iPhone lock feature.



Ok, all we need in the project is a UISlider, a UIImageView and a UILabel. In .h, we declared them as follows:

 IBOutlet UISlider *slideToUnlock;

IBOutlet UIButton *lockButton;

IBOutlet UILabel *myLabel;

IBOutlet UIImageView *Container;

The lockButton is just a control to enable you to enter the "Locked" status. Also we will be needing 3 methods to help us implementing the "Slide to Unlock" feature in our app.

 
-(IBAction)UnLockIt;

-(IBAction)LockIt;

-(IBAction)fadeLabel;

So, how do we go about implementing it. We need to think of the behaviour, of course. We want the user to slide the slider ball until the very end (right hand side), only then the screen be unlocked. Also, if the user slides half way or not until the very end, and let go (untouch) of the slider ball, we need to slide back the slider ball into initial position (value = 0, at the most left side).

Translating that behaviour into code means: Since the behaviour depends on untouch action, therefore we will use the "Touch Up Inside" delegate of the UISlider. So we will connect the "Touch Up Inside" method to the UnLockIt method.

Let's take a look inside the UnLockIt method - we need to check the value of slider (which equals to the location of the slider ball), and translate the behaviour we stated above into codes:
 
-(IBAction)UnLockIt {



if (!UNLOCKED) {



if (slideToUnlock.value ==1.0) {  // if user slide to the most right side, stop the operation 

// Put here what happens when it is unlocked



slideToUnlock.hidden = YES;

lockButton.hidden = NO;

Container.hidden = YES;

myLabel.hidden = YES;

UNLOCKED = YES;

} else { 

// user did not slide far enough, so return back to 0 position



[UIView beginAnimations: @"SlideCanceled" context: nil];

[UIView setAnimationDelegate: self];

[UIView setAnimationDuration: 0.35];

// use CurveEaseOut to create "spring" effect

[UIView setAnimationCurve: UIViewAnimationCurveEaseOut]; 

slideToUnlock.value = 0.0;



[UIView commitAnimations];



}

} 

}

You notice that we also declare a global variable of type BOOL to check the state of the lock. If the slider ball is at the most right, the value is 1.0 (this is the default max value of a UISlider, you can change in IB if you want), then execute the method to unlock it, in this example, just to hide the slider, label and so on and display the Lock button. If it is not reaching to the right side, then we use CoreAnimation to animate the auto sliding of the slider ball back to initial position of 0.0 (which is at the most left hand side).

Note that I use the UIViewAnimationCurveEaseOut, this animation curve starts out very fast immediately and then slows down at the end. This is to make it similar to a spring reaction.

You also notice we added a label in there. Now, if you see the label in your iPhone, it fades out as you slide the slider towards the right side, we can accomplish this by tying the "Value Changed" delegate of the UISlider to the method fadeLabel as below:

 -(IBAction)fadeLabel {



myLabel.alpha = 1.0 - slideToUnlock.value;



}

This is simple really. Whenever we move the slider ball from left to right, the value of the slider (that we named slideToUnlock), will increase from 0 to 1.0. But we want to change the label's alpha (opacity) from 1.0 to 0.0, therefore a simple invert is done by taking the max value of slideToUnlock and subtracting it to its current value. A better code would be to use

 
myLabel.alpha = slideToUnlock.maximumValue - slideToUnlock.value;

especially if you changed the maximum value to other than 1.0.

That's done with the behaviour of the slider. Now, what's left is just to customize the UISlider with custom slider ball. I also put a UIImageView (Container) at the back to align it nicely with the slider ball. You could also use the container image as the Slider's minimum and maximum track images.

NOTE: Just a little note, the customizing of UISlider must be done at viewDidLoad, otherwise the slider won't be made custom for some reason.

So under viewDidLoad (or if you wish you can put it under applicationDidFinishLaunching), we put the customization code of the UISlider:
 

// I set the track images to be nothing (just a clear image)

UIImage *stetchLeftTrack= [[UIImage imageNamed:@"Nothing.png"]

stretchableImageWithLeftCapWidth:30.0 topCapHeight:0.0];

UIImage *stetchRightTrack= [[UIImage imageNamed:@"Nothing.png"]

stretchableImageWithLeftCapWidth:30.0 topCapHeight:0.0];



// this code to set the slider ball image

[slideToUnlock setThumbImage: [UIImage imageNamed:@"SlideToStop.png"] forState:UIControlStateNormal];

[slideToUnlock setMinimumTrackImage:stetchLeftTrack forState:UIControlStateNormal];

[slideToUnlock setMaximumTrackImage:stetchRightTrack forState:UIControlStateNormal];

That's about it. Enjoy.

Tuesday, February 22, 2011

Best way to use UIImageView (Memory Optimized)

We use UIImageView a lot in our apps, right? At the most, we use it for a nice view backgrounds or even as button images.

The easiest way to set an image to the UIImageView is to use the following code:

 myImage.image = [UIImage imageNamed:@"myImage.png"];

This works. The code is short and simple and used to be my favourite code to use. But no more. Let me tell you why. For this tutorial, we are going to make use the Instruments to help you understand why this method is not memory optimized.

This tutorial also kinda teach you to check your app's Allocations (of memory) and what you should expect an app to behave in the memory world.

1. Using imageNamed will prepare a cache (depending on the size of image) which will NEVER be flushed out of the memory unless you reach a memory warning of some level, but by then its too late and your app will crash. Even when you set myImage.image = nil, the image is STILL IN MEMORY.

2. If you are using Interface Builder, and setting the image in Image View Attributes, that is also equal to imageNamed method. The image will be cached immediately when the app is ran.

3. To illustrate this, I created 2 UIImageViews in a single View. Created the IBOutlets for them so that we can easily set the image to it by code. I also add a button on the main View, so that we can switch between the 2 sub UIImageViews.

4. To illustrate this issue, 2 projects have to be created. One project uses imageNamed as the image setter, and the other uses imageWithContentsOfFile, which is the better image setter.

5. The imageNamed Project:
a) The project is simple, so I won't be explaining any of the normal codes. In this project, upon loading, we set the first UIImageView *firstImage. Upon tapping the button, we will set firstImage to nil, and then show the second UIImageView *secondImage.

b) Lets take a look at the Instruments tool of XCOde. The one we are interested now is the one called "Allocations". Allocations is a very effective tool to check your code for unreleased objects that is eating the memory when it is not used. The basic principle in the coding is, you must release what you no longer use.

c) To run it, simply Build the Project first. And then go to, Menu Run -> Run with Performance Tool -> Allocations. For the imageNamed Project, the result of the evaluation is as in the video shown below.
video

d) What happens when we run it is the app will cache the firstImage image first, since we used imageNamed in the viewDidload. After that, when I press the button, we can see that the "Live Bytes" increase another 3MB+ because we are using imageNamed on the second image. Note that we also write a code to set firstImage.image = nil, but the Live Bytes, remained the same. And after that even we keep on toggling the images while setting the other image to nil, it does not clear the memory at all.

___________

6. So now lets look at the better image setter, called imageWithContentsOfFile Project:
a) It is the similar project, but instead of using imageNamed, we make use of the imageWithContentsOfFile setter.

b) A little note on using it, is that you need to append a suffix of "/" at the beginning of the filename otherwise the path is incorrect and the image couldn't be loaded properly. The code is as follows:

 NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/myImage.png"];
myImage.image = [UIImage imageWithContentsOfFile:fullpath];

c)Run it the same way you did with the imageNamed project. The result of the evaluation if as in the video shown below.

video

(sorry for bad quality of video but its only at the beginning)

d) In this project, we will see the Live Bytes will only contain the memory of 1 image. In this case the photo of the bulls is about 3.3MB in total. And the photo of the kid on a bike is about 4.4MB in total. And as we toggle between the 2 photos, we can see the Live Bytes remain to be at lowest total in comparison to the imageNamed project.

e) While imageContents are superb for memory management, loading images this way is a little bit slow. So if you are just using a small sized UIImageViews in a larger quantity, it is probably better to use imageNamed method.

ImageName Project:


ImageContents Project:

Monday, January 17, 2011

How to Integrate iAd for OS3.2+ and Admob as Backup


I am impressed with iAd revenue given by Apple. It really surprises me. So I end up putting iAds for most of my free apps. Though, I'd like the app to be downloaded by OS3.2 users as well (wider user base). So, upon searching, I found the tutorial from Ray Wenderlich. It totally works! If your app is ran on 3.2, it will not cause a crash using this way. iAd is simply not instantiated in OS3.2.



This post is not really a step by step tutorial for the codings, but more of an explanation of what needs to be done in order to have iAd integrated in your app, with Admob as backup ad in OS3.2 and when iAd fails. Please read this post carefully. With the downloadable full project source code sample, you should be able to figure this out easily.

1. To get the Admob SDK, you need to be registered to Admob and add a new Site/Apps. Key in your app URL, and soon the Admob Publisher Code will be given and you can then download the Admob SDK built specifically for your app (basically the SDK will be pre-filled with your publisher code).

2. All you need to do is then copy 2 folders - Admob and TouchJSON into your app folder in Finder. Then drag these 2 folders in your XCode Project group. Then you need to add 5 Frameworks to your project. They are MediaPlayer, CoreGraphics, AudioToolBox, MessageUI, and QuartzCore.

3. For iAd, you need to add and weaklink the iAd.framework. Click on Targets->"App name" and get the info of it. Then go to General tab and underneath there is a list of frameworks. On the right side, there is a column called "Type". Click on the value "Required" and change to "Weak".

4. Now for the required codes to declare Admob and iAd. In .h of your viewcontroller, declare as below (read the comments in code below for more details):
#import "AdMobDelegateProtocol.h"

@class AdMobView;



@interface iAdMobViewController : UIViewController <AdBannerViewDelegate, AdmobDelegate> {

id _myAD; // we are declaring as id because OS3.2 won't know the existance of ADBannerView

AdMobView *adMobAd;

NSTimer *admobTimer;

IBOutlet UIButton *exampleBtn; // just to simulate repositioning objects

}



@property (nonatomic, retain) NSTimer *admobTimer;

@property (nonatomic, retain) id myAD;

@property (nonatomic, retain)  UIButton *exampleBtn;



-(void)createAdBannerView; // method to create iAd banner view

-(void)callAdmob; //method to create Admob view



// methods to show or hide iAd view upon receiving ad or failing to receive ad.

-(IBAction)moveAdOut; 

-(IBAction)moveAdIn;



// methods to show or hide Admob view upon receiving ad or failing to receive ad.

-(IBAction)moveAdMobOut;

-(IBAction)moveAdMobIn;



end;

Then in .m file, we need to include a header file for Admob only.
#import "AdMobView.h"

Most of the code above is pretty straight forward. Though NSTimer deserves a little explanation. Admob works a little different than iAd. For iAd, once we create the BannerView, retained it, then iOS will continue to call for adverts from Apple server every 30seconds (edit: only test iAd in SDK 4.0 is called every 30sec, actual iAd refresh is called every 3 minutes). It is done automatically. But for Admob, the SDK does not call for new ads automatically. For Admob, the ad will be called once everytime we create/alloc an AdMobView. If you see in the AdMob delegates, there is one function called requestFreshAd, though this just refresh the ad inside the view with new one WITHOUT calling the didReceiveAd delegate!

Our goal in this project is to make iAd the master ad server, and admob the secondary ad filler. So, in OS4.0, we instantiate iAd once, so the iOS will continue to send ad requests every 30 seconds. So we set the iAd to show if the ad is received, and set to create and show Admob ad if iAd fails. This cycle will continue forever. So we will be having iAd and Admob continuously showing.

Though, in OS3.2, iAd NEVER gets instantiate. So the iAd didFailToReceiveAd delegate will never get called, and that means Admob ad will never be instantiated as well! So we need to trigger the creating of Admob ad calling manually. And that's where admobTimer comes in the picture.

Testing the project can be painstaking at times. Because since we make iAd the master, and iAd Test ads fillrate is like 99%, it will take a while for Admob Test ad to appear. During running the project in simulator, monitor it together with Console so that you can see the logs every 30 seconds. Test the app with iPad Simulator 3.2 too, and it should not crash, and you should only see Admob ads in the iPad Sim3.2.

There are a few more things that is important in setting up the Admob Delegate functions.

1. The Publisher ID delegate. Key in YOUR Publisher ID in that string placeholder. (in your .m file)
- (NSString *)publisherIdForAd:(AdMobView *)adView {

return @"your admob publisher id here";  

}

2. To get the test Ads for Admob, put this delegate:
- (NSArray *)testDevices {

return [NSArray arrayWithObjects:

ADMOB_SIMULATOR_ID,                             // Simulator

nil];

}

3. To get test ads in your devices, just add your 40digits device ID as NSString into the array in the above delegate function. If you have more devices, just continue to add them to the array.
- (NSArray *)testDevices {

return [NSArray arrayWithObjects:

ADMOB_SIMULATOR_ID,                             // Simulator

@"your 40digit device ID here"

nil];

}

4. To get test ads in iAd, you don't need to do anything in Simulator. Even if you haven't added a new version with iAd enabled in iTunesConnect, you can still receive test ads in the iAds in simulator or device.