Wednesday, July 27, 2011

New/Better way of releasing object?

Noticed some codes are using a new (better?) way of releasing objects in the "dealloc". As below, an extra "," was added and then followed by assigning it to "nil"... Which is quite interesting...


- (void)dealloc
{
    [_window release], _window=nil;
    [_viewController release], _viewController=nil;
    [super dealloc];
}

Less typing required!

Not sure when did this start, but now when I create a new project in XCode 4, found that in the header ".h" file, the default property/variable disappeared!

As below, at the line where I put the "//", we used to have to repeat the declaration of "UIWindow *window" and "ScrollViewTestViewController *viewController;", now it all disappeared - which is cool as we can now save some typing...


#import <UIKit/UIKit.h>

@class ScrollViewTestViewController;

@interface ScrollViewTestAppDelegate : NSObject <UIApplicationDelegate> {

//


}

@property (nonatomic, retainUIWindow *window;

@property (nonatomic, retain) ScrollViewTestViewController *viewController;

@end

What is "ViewPort" ?

As I mentioned in this previous post, in the HTML code example I used this META tag "<meta name='viewport' content='initial-scale=1.0' />".

I learned that from Chapter 24 "Web Views" of book "Programming iOS4". The author says according to "Safari Web Content Guide" "if no viewport is specified, the viewport can change when the app rotates. Setting the initial-scale causes the viewport size to adopt correct values in both orientations."

I searched the net and found This article from Safari Web Content Guide which provides quite a lot of information and you should have a look to learn more about "viewport".

UIWebView with MathJax working!

After a few tests, I was able to get a few weird Math formulas display working in a UIWebView using MathJax as shown in screen dump below.


The codes are based on examples from This page on MathJax site, I stripped out the CSS/JS files and converted into a long NSString as below. Then based on parameter passed on from the caller, concatenated into a long string, write it into a temp HTML file.


    NSString *foo = @"<html><head><meta name='viewport' content='initial-scale=1.0' />"
    "<script type='text/javascript' src='http://www.mathjax.org/wp-includes/js/l10n.js?ver=20101110'></script>"
    "<script type='text/javascript' src='http://www.mathjax.org/wp-content/plugins/syntax-highlighter-mt/scripts/shCore.js'></script>"
    "<script type='text/javascript' src='http://www.mathjax.org/wp-content/plugins/syntax-highlighter-mt/scripts/shAutoloader.js'></script>"
    "<link type='text/css' rel='stylesheet' href='http://www.mathjax.org/wp-content/plugins/syntax-highlighter-mt/styles/shCore.css'/>"
    "<link type='text/css' rel='stylesheet' href='http://www.mathjax.org/wp-content/plugins/syntax-highlighter-mt/styles/shThemeDefault.css'/>"
    "<style type='text/css'>body { background-color: #d2d3d3; }</style>"
    "<script type='text/x-mathjax-config'>"
    "MathJax.Hub.Config({ MMLorHTML: { prefer: {Firefox: \"HTML\"} } });"
    "</script>"
    "<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/1.1-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML-full'></script>"
    "</head>"
    "<body>";
    
    NSString *foo2 = [foo stringByAppendingString:strContent];
    NSString *foo3 = [foo2 stringByAppendingString:@"</body></html>"];


Then in the main file, it's loaded into an UIWebView, with the content (also extracted from same test page).


    NSString *fName = @"test1.html";
    
    NSString *xContent = @"<p>\\["
      "\\left( \\sum_{k=1}^n a_k b_k \\right)^{\\!\\!2} \\leq"
      "\\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)"
      "\\]</p>"
      "<BR/>"
      "<p>\\["
      "\\frac{1}{(\\sqrt{\\phi \\sqrt{5}}-\\phi) e^{\\frac25 \\pi}} ="
      "1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} {1+\\frac{e^{-6\\pi}}"
      "|{1+\\frac{e^{-8\\pi}} {1+\\ldots} } } }"
      "\\]</p>";
    
    //write to temp file first
    [self writeStringToFile:tempDir fileName:fName content:xContent];
  
    //create UIWebView
    CGRect webRect = CGRectMake(10,10,300,400);
    myWebView =[[UIWebView alloc] initWithFrame:webRect];
    myWebView.scalesPageToFit = YES;
    myWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
myWebView.delegate = self;
        
    NSString *path4 = [tempDir stringByAppendingPathComponent:fName];
     
    NSURL* url = [NSURL fileURLWithPath:path4]; 
    NSURLRequest* req = [[NSURLRequest alloc] initWithURL:url]; 
    [myWebView loadRequest:req];
    [self.view addSubview:myWebView];
    [req release];
  
    activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
activityIndicator.center = self.view.center;
[self.view addSubview: activityIndicator];

Unfortunately, I don't know how to include the whole MathJax into the project yet (the size is 16MB even after compressed into .ZIP file!!!), so although the HTML is first written to local temp directory then loaded back, it still has to go out through Internet to load those .JS files - which might not be the best solution for "off-line" mode operation I guess.

The source project is available below. Note that for the content you have to change every "\" into "\\" otherwise it won't work as that's the escape character.


Source for UIWebViewTest

[Update 1] After tested from local directory, found that to have the whole MathJax fully functioning, you need:
(1) the main "MathJax.js" file, plus
(2) all the files under the 4 sub-directories: "config", "extensions", "fonts" and "jax".
Just that "fonts" one by itself is more than 10MB in size!
Definitely much easier to get everything from Internet then...

[Update 2] Further test shows that as below, the "*foo" can be even further simplified by removing some of the settings in the middle (about 9 lines) and it still works ok (Note: only tested in Safari 5.0.5).

    NSString *foo = @"<html><head><meta name='viewport' content='initial-scale=1.0' />"
    "<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/1.1-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML-full'></script>"
    "</head>"
    "<body>";

[Update 3] In case you wonder what does the following META tag mean, I will cover that in a separate post.
 "<meta name='viewport' content='initial-scale=1.0' />" 

[Update 4 (26/02/2012)] Please have a look at this new post about how to setup MathJax "Locally".

Friday, July 22, 2011

Any one knows how to create fractions, square roots and other math formulas?

Was looking for ways to create fractions, square roots and other math formulas by code in Objective-C but not very successful...

For example this 'Wolfram Math World' site has lots of stuffs (like the one using .GIF file shown below) but all done using .GIF files, wonder how they create those files?

[UPDATE 1] Saw some discussions about "MathJax", "jsMath" and a few other stuffs on the net, but most of them are about JavaScript libraries, not for Objective-C and none of them seem easy to beginners like me... Might have to park this idea for a while...

[UPDATE 2] Please see this post of mine which I got it working in a UIWebView.

Tuesday, July 19, 2011

Some fonts not printed correctly on "Cocoa with Love" site

Found this site called Cocoa with Love with lots of handy information, lots of them still too difficult for me unfortunately :-( ...

Was looking at this page called  Easy custom UITableView drawing, printed out from work to read it on the train. But as below (scanned from the print out), some of the words somehow not recognisable at all??!!
However when viewed from browser there's no problem at all.... very strange...

Checked the source, those fonts are covered in "<code></code>" tags, which are defined as below and doesn't seem to be unusual?


code, span.monospace {
font-family:Courier, monospace;
font-size:12px;
}

Not sure if this has anything to do with the printer or is it the CSS on the site. It's just not user friendly... Unless the author did that on purpose to stop people form printing their web pages - which I doubt it...


Any way, I learned 2 new things from that page:
(1) there's this tool called nib2objc which can convert NIB files into Objective-C, and 
(2) this free drawing tool called Inkscape
Will definitely give both of them a try!

Monday, July 18, 2011

Glass Button Generator

Was looking for ways to draw those nice glass buttons on the net, found this link from Anders Brownworth which not only generates a beautiful glass button, it also saved it as a .PNG file which you can then re-use in the future, which is pretty cool!

Played around with it a bit, and added some looping and tried to covered lots of colours (colorWithHue accepts value from 0 to 1 only)  and when executed will almost fill up the screen with glass buttons in different colours as shown below. Now I didn't spend lots of time in the calculation to make sure it covers all of the numbers, so you are welcomed to adjusted the parameters to different sizes and colours.

Also, before you run the code, please be aware that the following line controls where should all the image buttons be saved/written to your local drive and you should change it according to your system.


tmpStr = [tmpStr stringByAppendingFormat:@"/Users/qq/tmp/testButton%d_%d.png",ii,jj];


Then you will see lots of nice glass button files ready to be re-used in other projects.

Have fun!

Source for Glass Button image Generator

Sunday, July 17, 2011

How to assign initial values to variables in your init methods with proper memory management

A simple but important technique learned from Chapter 15 of the book "Learn Objective-C on the Mac", which I think is quite important when you are assigning initial values to variables in your init methods.



@implementation Thingie 
@synthesize name; 
@synthesize magicNumber; 
@synthesize shoeSize; 
@synthesize subThingies;

- (id)initWithName: (NSString *) n 
       magicNumber: (int) mn
          shoeSize: (float) ss {
    
    if (self = [super init]) {
        self.name = n; 
        self.magicNumber = mn; 
        self.shoeSize = ss; 
        self.subThingies = [NSMutableArray array];
    } 
    return (self);
}

"Notice that in the init method we’re using self.attribute on the left-hand side of the assignments. Remember that this actually means that we’re calling the accessor methods for those attributes, and these methods were created by @synthesize. We’re not doing a direct instance variable assignment. This object creation technique will get us proper memory management for the passed in NSString and for the NSMutableArray we create, so we don’t have to provide it explicitly."


Saturday, July 16, 2011

Colour Picker Test

Still don't know much about UIAlertView and other system default dialog boxes. Was testing this Colour Picker code from http://www.skylarcantu.com/blog/2009/08/14/custom-uialertview-color-chooser/

As screen dump above, quite nice but still don't fully understand some of the codes yet unfortunately...

For example, inside "presetSlidersWithColor" and "presetSlidersWithRandomColor", how come only calls
[self performSelector:@selector(redSliderValueChanged:) withObject:redSlider afterDelay:0.0];


Then, what about "greenSlider" and "blueSlider", don't they also have to be called?

Also this part about "setFrame" too...

- (void)setFrame:(CGRect)rect

Still got a lot more stuffs to learn...Now where was I? Got lost again... back to the schedule...

Sometimes, don't listen to the compiler

Was testing this "colour picker" code from http://www.skylarcantu.com/blog/2009/08/14/custom-uialertview-color-chooser/. As below, compiler gave me warning about "Using the result of an assignment as a condition without parenthesis". The suggestion is "use '==' to turn this assignment into an equality comparison" and "Place parentheses around the assignment to silence this warning".

I followed that and then noticed....wait...that's not right!

The author was actually combining the following 2 lines:


    self = [super initWithFrame];
    if (self) {
        

into 1 line:


    if (self=[super initWithFrame:frame]) {


If I use "==" instead of "=" as suggested, that would be wrong! So I guess sometimes we shouldn't listen to the compiler...

Wednesday, July 13, 2011

Strange XCode error when switching between XCode 3 and 4 - fixed

I have a machine at home running XCode 4 and a VMware virtual machine on my laptop running XCode 3. When I have to load the projects on different version on XCode, it gives me some strange error.

Opening XCode 4 saved projects on XCode 3 is easy, just change the "Project Properties" and choose the correct SDK.

But when I tried to open XCode 3 saved projects on XCode 4, as below it gives me tones of error "LLVM GCC 4.2 Error" "Operator '<' has no left operand", and the file that got those error is "usr/include/AvailabilityInternal.h" which I never heard of...
Took me a while to work out the fix. As shown below, I have to change the "Base SDK" to "Latest iOS(iOs 4.3)" and then it start working...

Do we really need "UIViewController"?

I studied the "Scratch Off Effect" code from http://buildingmyworld.wordpress.com/ and found a very interesting thing.

There's only a "main.h", an "AppDelegate", 2 "UIView" and - - - an "UIViewController" which is not been used at all. If you look at the blog, the author also mentioned "btw: there is a view controller called ScratchTiceketViewController. Just ignore it. It was my test view controller and I’m to lazy to remove it :) )"

So I inserted a few NSLog in each of the methods to show how/when each method been called, and removed that "ScratchTicketViewController" completely. The code still works! What the....

This is totally different from what I learned so far - so we can have a application that has no UIViewController at all, very interesting!

Next, I tried to add an UIView and an UIViewController to the project and compare the differences.

For UIView, as below it only has 3 methods, and one of them - "drawRect" disabled -- I remember seeing that name in previous Quartz 2D test project. I guess if you need any other methods, can still be triggered from the "initWithFrame" method.


@implementation UIView1

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

- (void)dealloc
{
    [super dealloc];
}

@end

However, for UIViewController it's a lot more complicate. As below there are a few extra ones: "loadView", "viewDidLoad", "viewDidUnload", "didReceiveMemoryWarning" and "shouldAutorotateToInterfaceOrientation". Which is definitely more complicate and powerful than the simple UIView above.

@implementation UIViewController1

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
}
*/

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

I guess it all depends on the purpose of the code, if it's just a simple test project/application, which you don't care whether there's orientation change or memory warning or use NIB files, a simple UIView should be sufficient. For a more "normal", "fully functioning" project/application which is to be submitted to App Store, you would definitely still have to use UIViewController.

Ah! Feels good to learn new things everyday!

Better "TestingScratchTicketEffekt" project than mine

Had a quick look at that http://buildingmyworld.wordpress.com/ link I mentioned in previous post.

As below, it works like magic! First it shows this full screen covered in orange colour. If you move your finger/mouse pointer around, it will "scratch" off the orange colour and reveal the nice Apple image below.

The source code is also available on that blog. Thanks for the sharing and it's definitely much better than mine. The best part is - everyone knows how to do it now, ha ha!

Image Mask Test Project

As mentioned in this post on iPhone Dev SDK forum, there's this discussion about how to create a dynamic mask. Where a mask layer is presented above another photo layer and when user moves his/her finger on it, the photo below will be revealed.


This sounds like an interesting project, although have to admit it's far beyond my level of objective-c skills..... Did some research and found 2 links:
http://www.iphonedevsdk.com/forum/245649-post15.html
http://www.ifans.com/forums/showthread.php?t=132024

which gave me some idea. I sort of combined the two and created a small project with "similar" effect. Unfortunately I don't know how to "fill the whole screen with a solid colour" yet (yes it's a bit embarrassing...), so I sort of do it in a slightly different way.

As shown below, when the project starts, it shows the full image, then user starts moving finger to draw something (this mimics the fill up full screen with solid colour part :-P ). After that, click on "switch" to switch to "erase" mode, and the then when user moves finger around, the red paint get erased and revealed the photo below.....

Ok, I agree this is not exactly what the original request is asking for, but I guess if somehow i can work out how to fill up the full screen with some colour, I can just start with the "erase" mode and that should be quite close to the original request.... Leave this for future project then.

[UPDATE] See this post about info from analysing source code from the site http://buildingmyworld.wordpress.com/ which has better solution than mine.

Source for Image Mask Test Project

TicTacToe V2.1 leaking fixed

Ok, spent some time today playing around "instruments" and browsing the net learning how to fix memory leak. I think it should be fixed now, as when I re-run "instruments" the result is as shown below, there's no more leaking! Yeah!

Most of the issues are related to NSString handling. If you compare the V2.1 with V2.0 and you will easily see the differences.

Alright, spent enough time on TicTacToe, time to move on to the next project....

Source Code for TicTacToe V2.1 (Leaking Fixed)

Tuesday, July 12, 2011

Open Source Game: TicTacToe Ver 2.00

After about a week's hard work, I finally merged TicTacToe Ver 1 with the multi-view switching project and created a updated version of TicTacToe called Ver 2.00 which has multiple view controllers. Some high level information as below.

  1. Instead of "everything in single main.m file" as in Ver 1, Ver 2 is splited into different files.
  2. There are total of 4 View Controllers. The main one only in charge of switching between the 3 child view controllers. The 3 child view controllers are Intro, GamePlay and Ending. Each looks after different parts of the game. 
  3. Added 3 different difficulty levels for single player mode: beginner, advanced and expert. In beginner mode, computer will always play randomly. Advanced mode is with the 2 special conditions disabled. Expert mode has those conditions included. 
  4. Intro View Controller looks after collect info about single/two player mode and the 3 difficulty levels.
  5. GamePlay View Controller mostly remain unchanged from Ver 1 except now it highlights the winning row at the end.
  6. Ending View Controller shows the final score/result, and ask player to choose whether try again or start a new game.
  7. Also created a new class "GameData" to store all game related data. This isolates the game logic and data, plus makes it easier to handle the data, in case say need to export/store the data into file system or whatever other purpose.
Another thing I learned, was to always use "@class xxxxclassname" in ".h" header files to reference other classes, only use "#import" in the ".m" files to avoid looping declaration errors.

Original plan was to use this as practice and build a simple multi-view template/platform so that I can further expand it into more complicate projects in the future.

However, I felt like been punched on the face after I did a quick run using "Instruments". As shown below it's leaking memory quite badly - see the purple little bars on top of the screen.

Don't have much knowledge about how to use "Instruments" to work out which part is leaking yet, so there's surely still a lot of things to learn before I can build more complicate stuffs.

Any way, if any of you still interested in the "leaky" TicTacToe V2", the link is below.

[UPDATE 2] Please see this post for TicTacToe V2.1 (Memory Leak Fixed)

TicTacToeV2

How to print BOOL in NSLog

Was trying various ways to dump the value of a BOOL in NSLog for debugging and couldn't get it to work properly. Did a quick search on the net and quickly found the solution as below, just convert it into a NSString!


NSLog(@"isTwoPlayerMode=%@", ([currentGameData isTwoPlayerMode] ? @"YES" : @"NO"));

Tuesday, July 5, 2011

How to prevent the screen from sleeping

Learned how to prevent the screen from sleeping from Nick's SpaceBubble code, and his comment about AngryBirds is quite funny...



// Prevent the screen from sleeping!  Important!!  (AngryBirds doesn't do this btw...annoying)
[application setIdleTimerDisabled:YES];

What? Can't play any sound/music on iPhone simulator?

Was trying to test some sound/music but nothing worked. Checked the net and looks like it only works in the real device... Damn...

Please let me know if any of you know how to get sound to work on simulator...

[UPDATE] The content of this post is no longer valid, please see this post and many others which shows how to play sound/music/video in simulator.

Monday, July 4, 2011

Speedo Meter Test Project

I got this speedo meter test project working. It's quite interesting seeing the needle slowly moves to different positions when you clicked on any of the 4 buttons.

Move #1 - 0 degree
Move #2 - 90 degrees
Move #3 - 180 degrees
Move #4 - 270 degrees

But would certainly need a lot more work to make it moves/trembles/shakes like a speedo meter in the car when you step on the accelerator....

The needle image is from https://github.com/jfryman/velometer



The loadView method of the view controller only did the following plus the button creation work:


    myImageRect = CGRectMake(0.0f, 200.0f, 320.0f, 109.0f);
    myImage = [[UIImageView alloc] initWithFrame:myImageRect];
    [myImage setImage:[UIImage imageNamed:@"VM1_D.png"]];
    myImage.opaque = YES
    [self.view addSubview:myImage];
    [myImage release];


Then when clicked, each of the button's action simple do the following, with different parameter used. #1 is "M_PI*0.0", #2 is "M_PI*0.5", #3 is "M_PI*1.0" and #4 is "M_PI*1.5".


    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.5];
    
    myImage.transform = CGAffineTransformMakeRotation(M_PI*0.0);
    
    [UIView commitAnimations];

Source Code for Speedo Meter Project (Updated)

Sunday, July 3, 2011

Multi-View switching Test Working!

Thanks to Nick's Space Bubble Source Code, I created this test NIB-less project with 4 simple views. As shown below, the Main one has 3 buttons, click on any of them will trigger the switch to one of the 3 child views - each have a different background colour, and only have one button to close the child view and return back to the main view.

As the child view releases itself when the button been clicked, the main view didn't need to release each child views.

Please let me know if you found any problem (memory leaking?) or need further information.

Source Code for Multi View Switching Project (Updated)

Open Source Game: TicTacToe Ver 1.00

Finally got ver 1.00 of my first game - TicTacToe completed. As usual, it's a NIB-less design. I have put everything in one "main.m" but it shouldn't be too difficult for you to split into separate files if required.

Link to full source code listed below, I tried to make the code looks tidy and put in as many comments as possible within limited time. Drop me some comments on the blog or email me if you need any further info.

Well, actually the 2 players mode has been fully working for a few days. It's just that in the single player mode, computer player wasn't "smart" enough until now.



Some information about the game:
1) I use "buttons" instead of "touch" events like the others
2) Originally I used NSMutableArray for "gameArray" (to store board status) and "checkWinArray" (to check each of the 8 possible winning conditions), but wasn't very comfortable about it. In the end both switched back to use simple arrays.
3) Original plan was to show a separate view for users to pick single/two player mode, but couldn't get it to work, so just use the UIAlertView.

Known issues/limitation:
1) Doesn't support device rotation "yet" --> will fix that later if I can find some time
2) Won't save application status if interrupted --> will fix that later if I can find some time
3) No music/sound --> I have to admit that I have read some examples from books/net about how to play music, but haven't actually try any, this will be for future versions.

I am not very sure if there's any memory leak as I am still not experienced with it, please let me know if you found any!! Please also kindly let me know if you found any bug or problem with it.

Oh yes, one more very important thing: So far, I wasn't able to beat the computer player in single player mode. Let me know if any of you can find a way to win her!!!

Enjoy!

[UPDATE 1] Please see this post for TicTacToe V2.00
[UPDATE 2] Please see this post for TicTacToe V2.1 (Memory Leak Fixed)

Note: I quite like the "Take a kid fishing or hunting license" by Nicholas Vellios (http://www.vellios.com). To make it easier for people living in big cities like me, I slightly modified a bit and call it "Take your kids, family or love ones for a few hours of outdoor activity license"...ha ha...
Source Code for TicTacTow Ver 1.00 (Updated)