TwitterCounter for @bigclick_dean

dBlog.com.au

My Development Blog

Archive for the ‘ Web Development ’ Category

Lithium has finally been released!

Picture 4

I see you asking “What is Lithium and why have I never heard of it before!?!?”

The answer…Lithium is a fork (Cake3) of the popular CakePHP framework and was born out of a split in the CakePHP development team (mainly Lead Developer Nate Abele).

Lithium looks to rewrite the Core codebase and make use of some new PHP 5.3 features…like namespaces!!!

If you want to check out the project and have a play then head on over to http://li3.rad-dev.org/

Stay tuned for some of my initial impressions in a future post.

-Dean

Popularity: 1% [?]

Big Click Studios is a dynamic company based on the NSW Central Coast with a relaxing and innovative work environment.

Fantastic office just minutes from the beach and train station. You will be working on many of our current and upcoming web development projects all bursting at the seams begging for the right person to dig their teeth into!

Essentials:

  • PHP5 + MySQL
  • XHTML + Javascript (jQuery a bonus) & CSS
  • An eye for well structured code and clean database structures
  • Understanding of Object Orientated Programming

Bonuses:

  • CakePHP framework
  • AJAX
  • Flash / Actionscript 2 & 3

Personal characteristics:

  • Must be able to work as part of a team
  • Proactive involvement in the business (we work closely with all staff to provide a safe, fun and mentally challenging environment)
  • Strong communication skills (both written and spoken)
  • Xbox skills are not required but highly desired if you dont want to get whooped at lunch!

For more information please send an email to jobs@bigclick.com.au or give us a call on 1300 677 924.

Look forward to hearing from you soon!

Popularity: 1% [?]

I use CakePHP on a day to day basis for project ranging from a single controller with a couple of views through to projects with large amounts of Controllers, Models, Views and Relationships.

This morning I was trying to build a simple Google Analytics component (which I will release as soon as it is done) and I needed to use the Session component…easy enough I hear you say…WRONG! I sat there for over an hour trying to figure out why my session was clearing every time I refreshed.

I searched high and low to find a solution, I tested the PHP session configuration by turning off “Session.start” in core.php and using the php “session_start()” function instead, everything worked fine.

After pulling out all my hair (what was left of it), I started thinking that it could be something to do with something being output before the header. I wasn’t getting any “Header Already Sent” warnings but I was still skeptical.

BINGO! I removed a single space after the closing php tag in one of my controllers and everything started working again.

It was so simple yet I have seem multiple threads on forums with the same problem but with no posted solution, hence why I am posting this for future reference (and when I inevitably forget).

So when troubleshooting CakePHP sessions make sure the first thing you do is remove any excess whitespace from your controllers, models and components.

A simple space after the ?> tag can cause all sorts of weird Session behaviour.

Popularity: 1% [?]

Why did I do it?

While working on a client project I needed a way to heavily integrate with Twitter for an interactive competition. I could have built a quick and dirty script to do this but I knew that I would be dealing with more clients that wanted Twitter integration.

What did I do?

I built a CakePHP Component to access all the Twitter API features along with the Twitter Search API for Searching/Trending.

There are already some Twitter API components for CakePHP but they all had their own little bits that I didn’t like so I decided to whip one up and share it for everyone to use.

As the component is 1140 lines I wont be posting it here in the article, but you can view the source code here.

How does it all work?

There is nothing like a fully functioning example to show you how to use it! So I have built a quick replica of the Twitter homepage to give you a feel for it.

View the example first to see what we will be building, it is updated every refresh and everything is pulled straight from Twitter’s API.

First up you will need to put the Twitter Component into your /app/controllers/components/ folder and call it twitter.php, you can find the text version here or download the source files at the bottom of the page.

Now create a new controller called twitter_controller.php and put the following content into it. Don’t forget to change the {USERNAME} and {PASSWORD} place holders to your Twitter details.

<?php
/**
* Twitter Controller
*
* This class is used to manage twitter communication
*
* @version 0.1
* @author Dean Collins <dean@bigclick.com.au>
* @project dblog
*/
class TwitterController extends AppController {
	/**
	* Controller Name
	* @access public
	* @var string
	*/
	var $name = 'Twitter';

	/**
	* Components that are used in this controller
	* @access public
	* @var array
	*/
	var $components = array('Twitter');

	/**
	* Models that are used in this controller
	* @access public
	* @var array
	*/
  	var $uses = array();

	/**
	* Helpers
	* @access public
	* @var array
	*/
  	var $helpers = array('Text', 'Html');

	/**
	* Default action
	*
	* The index function is used as a default action, in this case it will replicate your twitter page
	*/
	function index() {
		$this->layout = 'twitter';
		$this->Twitter->username = '{USERNAME}';
        $this->Twitter->password = '{PASSWORD}';
		// Grab the recent activity
		$feed = $this->Twitter->statuses_friends_timeline();
		// Grab the users details
		$user_details = $this->Twitter->account_verify_credentials();
		// Get your friends
		$friends = $this->Twitter->statuses_friends();
		// Get your followers
		$followers = $this->Twitter->statuses_followers();

		$this->set('feed', $feed);
		$this->set('user_details', $user_details);
		$this->set('friends', $friends);
		$this->set('followers', $followers);
	}

}
?>

Now create a new layout in your /app/views/layouts/ called twitter.ctp and put the following content in:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CakePHP/Twitter API Example</title>
<style type="text/css">
/* v1.0 | 20080212 */

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	vertical-align: baseline;
	background: transparent;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}

/* remember to define focus styles! */
:focus {
	outline: 0;
}

/* remember to highlight inserts somehow! */
ins {
	text-decoration: none;
}
del {
	text-decoration: line-through;
}

/* tables still need 'cellspacing="0"' in the markup */
table {
	border-collapse: collapse;
	border-spacing: 0;
}

</style>
</head>

<body>
<div style="top: 0px; left: 0px; width: 100%; height: 45px; padding-top: 20px; margin-bottom: 10px;">
	<div style="width: 800px; margin: 0 auto;">
    <h1 style="font-size: 24px;">CakePHP Twitter API Class Example</h1>
    </div>
</div>
<?php echo $content_for_layout; ?>
</body>
</html>

Finally create a new view under /app/views/twitter/ called index.ctp and put the following content in:

<style type="text/css">
body { font-size: 12px; font-family:Arial, Helvetica, sans-serif; background-image: url('<?php echo $user_details['User']['profile_background_image_url']; ?>'); background-attachment: fixed; background-repeat: no-repeat; }
.status_update img, .avatar { float: left; width: 48px; height: 48px; margin-right: 10px; }
.status_update { overflow: hidden; color: #333333; font-size: 12px; padding: 5px; border-bottom: 1px dashed #333; }

.status_update:hover { background-color: #CFF }

a {color: #0084B4;}
#lcol { width: 600px; border-right: 1px solid #333; float:left; }
#rcol { width: 180px; padding: 10px; float:left;}
#wrapper {width: 801px; margin: 0 auto; border: 1px solid #333; overflow: hidden; background-color: #FFFFFF}

#user_stats { margin-left: 15px; overflow: hidden; }

#user_stats a { color: #333333; display: block; float: left; font-size: 20px; text-align:center; text-decoration:none; background-color: transparent;}

#user_stats a span { font-size: 12px; color: #0084B4; }

#profile_title { font-size: 18px; margin-bottom: 10px; overflow: hidden; }

.avatar_small { width: 24px; height: 24px; }

.avatar_list { list-style: none; list-style-type:none; overflow: hidden }

.avatar_list li { float: left; }

#rcol h2 { font-size: 18px; padding: 5px; margin-bottom: 5px; margin-top: 10px; }
</style>
<div id="wrapper">
<div id="lcol">
    <ol>
    <?php foreach($feed['Statuses']['Status'] as $status) { ?>
    <li class="status_update">
    <img src="<?php echo $status['User']['profile_image_url']; ?>">
    <p><?php echo $status['text']; ?></p>
    </li>
    <?php } ?>
    </ol>
</div>
<div id="rcol" style="background-color: #<?php echo $user_details['User']['profile_sidebar_fill_color']; ?>">
    <div id="profile_title">
        <img class="avatar" src="<?php echo $user_details['User']['profile_image_url']; ?>"/>
        <?php echo $user_details['User']['screen_name']; ?>
   	</div>
    <strong>Name</strong> <?php echo $user_details['User']['name']; ?><br/>
    <strong>Location</strong> <?php echo $user_details['User']['location']; ?><br/>
    <strong>Web</strong> <a href="<?php echo $user_details['User']['url']; ?>"><?php echo $text->truncate($user_details['User']['url'], 20, '...'); ?></a><br/>
    <strong>Bio</strong> <?php echo $user_details['User']['description']; ?><br/>
    <div id="user_stats">
        <a href=""><?php echo $user_details['User']['friends_count']; ?><br/><span>following</span></a>
        <a href="" style="margin-left: 20px;"><?php echo $user_details['User']['followers_count']; ?><br/><span>followers</span></a>
    </div>
    <h2>Followers</h2>
    <ul class="avatar_list">
    	<?php foreach($followers['Users']['User'] as $follower) { ?>
        	<li><a href="http://www.twitter.com/<?php echo $follower['screen_name']; ?>/" target="_blank"><img alt="<?php echo $follower['screen_name']; ?>" width="24" height="24" class="avatar_small" src="<?php echo $follower['profile_image_url']; ?>"/></a></li>
        <?php } ?>
    </ul>

    <h2>Following</h2>
    <ul class="avatar_list">
    	<?php foreach($friends['Users']['User'] as $follower) { ?>
        	<li><a href="http://www.twitter.com/<?php echo $follower['screen_name']; ?>/" target="_blank"><img alt="<?php echo $follower['screen_name']; ?>" width="24" height="24" class="avatar_small" src="<?php echo $follower['profile_image_url']; ?>"/></a></li>
        <?php } ?>
    </ul>
</div>
</div>

And that’s it! You can head to http://yourcakeinstall.com/twitter and you should see a Twitter-like page with all your details with friends, followers, tweets, etc.

You can see my example over here

There is ALOT you can do with the data from Twitter so please let me know if you build something using this component and I will chuck a link up here for you.

Download the Source Files

You can download the source files, including the above example below.

CakePHP/Twitter API Component Download

Don’t forget to follow me on twitter and subscribe to my RSS to stay in the loop.

Popularity: 1% [?]

I have been working on a clients project recently and really didn’t like the way the standard selects looked on the page and as we all know they are impossible to style consistently across all browsers. Being a jQuery fan I knew that there must have been an existing plugin to help…but alas there were many plugins that kind of worked, some of them didn’t include a full feature set, some didn’t work in all browsers and some didn’t degrade back to regular selects when needed (e.g. GoogleBot, Screen Readers, no JavaScript, etc).

I did however manage to find a reasonable good custom select over at http://www.adelaidewebdesigns.com/2008/08/01/adelaide-web-designs-releases-customselect-with-icons (even happened to be a fellow aussie!). It wasn’t perfect and it wouldn’t allow for multiple selects on the one page and the icons weren’t really what I needed. Reading through the comments I found that someone else (http://www.ildavid.com/dblog/selectcustomizer/) had made some modifications to allow for multiple selects on the one page. This was great I was getting closer to the solution that I needed, but there were still some issues like keyboard navigation and the ability to click anywhere in the window to close the select just like a regular select.

So I set out to further modify the code and put in some of my own requirements and then re-share it, I have managed to get the drop-down to close when you click outside it, I have also introduced keyboard navigation (up, down and enter). To get the keyboard navigation working I needed to use the scrollTo plugin to allow smooth scrolling up and down in the select.

There are still a few minor bugs that need to be fixed but it works enough for me, one bug is that in IE you need to click in the drop-down area if you don’t want the page to jump when using the keys.

I would also like to get the menu to activate when a user is tabbing around the site, but that’s a job for another rainy day!

$.fn.SelectCustomizer = function(){
    // Select Customizer jQuery plug-in
	// based on customselect by Ace Web Design http://www.adelaidewebdesigns.com/2008/08/01/adelaide-web-designs-releases-customselect-with-icons/
	// modified by David Vian http://www.ildavid.com/dblog
	// and then modified AGAIN be Dean Collins http://www.dblog.com.au
    return this.each(function(){
        var obj = $(this);
		var name = obj.attr('id');
		var id_slc_options = name+'_options';
		var id_icn_select = name+'_iconselect';
		var id_holder = name+'_holder';
		var custom_select = name+'_customselect';
        obj.after("<div id=\""+id_slc_options+"\" class=\"optionswrapper\"> </div>");
        obj.find('option').each(function(i){
            $("#"+id_slc_options).append("<div title=\"" + $(this).attr("value") + "\" class=\"selectitems\"><span>" + $(this).html() + "</span></div>");
        });
        obj.before("<input type=\"hidden\" value =\"\" name=\"" + this.name + "\" id=\""+custom_select+"\"/><div id=\""+id_icn_select+"\">" + this.title + "</div><div id=\""+id_holder+"\" class=\"selectwrapper\"> </div>").remove();
        $("#"+id_icn_select).click(function(a){
			if($("#"+id_holder).css('display') == 'none') {
				$("#"+id_holder).fadeIn(200);
				$("#"+id_holder).focus();
				a.stopPropagation();
				$(document).keypress(function(e) {
					if(!e) var e = window.event;
					e.cancelBubble = true;
					e.returnValue = false;
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
				});
				$(document).keyup(function(e) {

					if(e.which == 40) {
						var lastSelected = $("#"+id_holder+" .selectedclass");
						if(lastSelected.size() == 0) {
							var nextSelected =  $("#"+id_slc_options+" div:first:");
						} else {
							var nextSelected = lastSelected.next(".selectitems");
						}
						if(nextSelected.size() == 1) {
							lastSelected.removeClass("selectedclass");
							nextSelected.addClass("selectedclass");
							$("#"+custom_select).val(nextSelected.title);
           					$("#"+id_icn_select).html(nextSelected.html());
							var rowOffset = (nextSelected.offset().top - $("#"+id_holder).offset().top);
							if(rowOffset > 130) {
								$("#"+id_slc_options).scrollTo(($("#"+id_slc_options).scrollTop() + 27) +  "px");
							}
						}

					} else if(e.which == 38) {
						var lastSelected = $("#"+id_holder+" .selectedclass");
						var nextSelected = lastSelected.prev(".selectitems");
						if(nextSelected.size() == 1) {
							lastSelected.removeClass("selectedclass");
							nextSelected.addClass("selectedclass");
							$("#"+custom_select).val(nextSelected.title);
           					$("#"+id_icn_select).html(nextSelected.html());
							var rowOffset = (nextSelected.offset().top - $("#"+id_holder).offset().top);
							if(rowOffset > 0) {
								$("#"+id_slc_options).scrollTo(($("#"+id_slc_options).scrollTop() - 27) +  "px");
							}
						}
					} else if(e.which == 13) {
						$("#"+id_holder).fadeOut(250);
						$(document).unbind('keyup');
						$(document).unbind('keypress');
						$('body').unbind('click');
					}

				});
				$('body').click(function(){
					$("#"+id_holder).fadeOut(200);
					$('body').unbind('click');
					$(document).unbind('keyup');
					$(document).unbind('keypress');
				});
			} else {
				$("#"+id_holder).fadeOut(200);
				$('body').unbind('click');
				$(document).unbind('keyup');
				$(document).unbind('keypress');
			}

        });
        $("#"+id_holder).append($("#"+id_slc_options)[0]);
		$("#"+id_holder).append("<div class=\"selectfooter\"></div>");
		$("#"+id_slc_options+" > div:last").addClass("last");
        $("#"+id_holder+ " .selectitems").mouseover(function(){
            $(this).addClass("hoverclass");
        });
        $("#"+id_holder+" .selectitems").mouseout(function(){
            $(this).removeClass("hoverclass");
        });
        $("#"+id_holder+" .selectitems").click(function(){
            $("#"+id_holder+" .selectedclass").removeClass("selectedclass");
            $(this).addClass("selectedclass");
            var thisselection = $(this).html();
            $("#"+custom_select).val(this.title);
            $("#"+id_icn_select).html(thisselection);
            $("#"+id_holder).fadeOut(250);
			$(document).unbind('keyup');
			$(document).unbind('keypress');
			$('body').unbind('click');
        });
    });
}


You can see a working demo here

You can also download a full working example here

Popularity: 2% [?]

Hi Everyone,

Sorry about the delays, I have been flat out with changing jobs (starting my own business actually) and getting all that setup and running smoothly.

I am hoping to get back into the iPhone tutorial writing headspace very soon and I have some great ideas to put down, the first one will be a lengthy (probably 10 part) tutorial series on developing a complete RSS application that uses SQLite, XML, Multiple Views, Save States, Caching, etc

I also have a simple puzzle game in the works that I would love to turn into another tutorial series so you can get a jump start on your iPhone Game Development.

Being in the Web/Application Development “scene” I have decided to give the whole Twitter craze a go and to see what all the fuss is about, so you can follow me by clicking the icon on the right.

If youo have any ideas or anything you would like me to write about then please leave a comment and I will give you a buzz.

Thanks,
Dean

P.S. Check out my new business at http://www.bigclick.com.au

Popularity: 3% [?]

If you are here I am guessing that you are interested in iPhone/iTouch development and are looking for a place to start. Due to Apple’s NDA on the iPhone SDK there really isn’t much information out there on getting started with iPhone development, by writing this tutorial I hope to give people the confidence to get started developing on the iPhone and also to help myself get my head around it.
Lets get started

1. Getting your development environment setup

You will need a copy of the iPhone SDK (available for free at http://developer.apple.com/iphone). Once you have downloaded the installer (it is pretty big, 1GB+) you will need to let it run and to install all the required components.

By default the installer doesn’t add any icons to anywhere so you will have to navigate to /Developer/Applications to find the tools that you will need, I suggest that you drag XCode and Interface Builder to your dock as you will be using them alot!

Fire up XCode to make sure that it launches OK, if so then you are ready to get into it!

2. Getting the TouchXML Libraries

As you cannot use the standard NSXML* libraries for iPhone development (they will work in the simulator but not when you try to deploy the app to the real hardware, I found out the hard way after working on an app for days!) we will be using the TouchXML library from TouchCode

You will need to check the latest code out from the TouchXML SVN Repository, if you dont know how to use SVN I have included the required commands below.

Launch a new Terminal window
Create a new folder called “ExtraLibraries” where you would like to keep your iPhone development libraries (I save mine in /Developer/ExtraLibraries/)

mkdir /Developer/ExtraLibraries

Change into the new folder

cd /Developer/ExtraLibraries

Run the SVN checkout code

svn checkout http://touchcode.googlecode.com/svn/trunk/ touchcode-read-only

You will see the filenames scrolling up the screen and it should only take around 30 seconds to grab all the required files.

Now you have the TouchXML libraries on your local machine ready to start creating your first iPhone app.

3. Setting up your New Project

Now its time to get into the hands on development, start up XCode if you haven’t already and click File > New Project and you will see the window below.

New Project Window

Double click on “Navigation-Based Application”, enter name your project “AdvancedBlogTutorial” and click Save.

You should see the following screen appear with all of your project files.

Initial Project Window

You can lay this screen out any way you wish but my favourite is to make the screen as large as possible and to drag the horizontal resizer all the way to the top to allow for the largest possible “code view” area as possible, like below.

My Development Layout

4. Including TouchXML in our project

As we are using TouchXML for our xml parsing, we will need to import the required files and also edit some of the project settings.

In the menu bar click Project > Edit Project Settings and a new window will appear with 4 tabs at the top (General, Build, Configurations and Comments). We are only interested in the “Build” tab at the moment, so go ahead and click the “Build” Tab and the following window will appear.

Default Project Settings Window

The settings that we are interested in are “Header Search Paths” and “Other Linker Flags”, you can easily find these by typing the beginning of the name into the “Quick Find” at the top right of the window.

You need to add “/usr/include/libxml2″ to the “Header Search Paths” and you need to add “-lxml2″ to the “Other Linker Flags”.

Once you have done this you can close the settings window and you will be back at your project window.

Now that the libxml2 libraries have been included you will need to import the TouchXML files to your project, to do this simply right click on the “Classes” folder in the left hand pane and click Add > Existing Files…

You will be presented with a finder window and you will need to navigate to the location that you checked the TouchXML files out to (in my case it was /Developer/ExtraLibraries/) and then keep going to the following path “touchcode-read-only/TouchXML/Common/Source/” and select all the files and click “Add”. You will be presented with the following screen:

Add files dialog

Leave everything as default and click “Add” .

You should now see the CXML* files in your left hand pane and they are now available for your application to use.

We are now finally setup and ready to get going.

5. Setting up our Variables, Outlets and Classes

As we used the “Navigation-Based Application” template, much of our layout and code structure has already been created for us. We could have started this from scratch but for simplicity sake it is much easy to use one of the default templates.

Open up the “RootViewController.h” file by expanding the “Classes” folder in the left hand pane and clicking once on “RootViewController.h”, you should see the contents of the right hand pane change to that of the file you selected.

By default you will see

//
//  RootViewController.h
//  AdvancedBlogTutorial
//
//  Created by dBlog on 15/09/08.
//  Copyright __MyCompanyName__ 2008. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController {

}

@end

Change the code to the following

#import <UIKit/UIKit.h>
#import "TouchXML.h"

@interface RootViewController : UITableViewController {
    // This is the outlet for the blog view, it will allow the data from the controller to be used in a view
    IBOutlet UITableView *blogTable;

    // blogEntries is used to store the data retrieved from the RSS feed before being added to the view
    NSMutableArray *blogEntries;

    // loadSwirlie will display a loading overlay while the data is downloaded from the RSS feed.
    UIActivityIndicatorView *loadSwirlie;
}
@end

The first line, “#import “TouchXML.h”", will import the TouchXML library for us to use in this Controller, it is very important because if we do not include it here we will not be able to access any of the TouchXML features.

The second line, “IBOutlet UITableView *blogTable;”, will allow our view to access data from the controller, this will be where we add the individual blog entries.

The third line, “NSMutableArray *blogEntries;”, creates a new Mutable Array called blogEntries that will be where we store the RSS feed items.

Finally the forth line “UIActivityIndicatorView *loadSwirlie;”, is a view that will overlay the default “Load Swirlie” while the RSS feed is being downloaded, this is especially helpful when accessing via EDGE or when trying to read large feeds.

Save the file.

6. Digging into the core code!

Now that we have the headers all setup and our TouchXML libraries included we are ready to start on the real workhorse of the application, the RSS reader!

Open up the “RootViewController.m” file the same way that you did in the previous step.

You will see alot more code in this file as when the project was created from the template it also created most of the basic code, we will be using some of the auto-generated code and also adding some of our own.

The first thing that we want to do is to make our RSS grabbing function, to do this just paste the following code below the “@implementation RootViewController” line.

// grabRSSFeed function that takes a string (blogAddress) as a parameter and
// fills the global blogEntries with the entries
-(void) grabRSSFeed:(NSString *)blogAddress {

    // Initialize the blogEntries MutableArray that we declared in the header
    blogEntries = [[NSMutableArray alloc] init];	

    // Convert the supplied URL string into a usable URL object
    NSURL *url = [NSURL URLWithString: blogAddress];

    // Create a new rssParser object based on the TouchXML "CXMLDocument" class, this is the
    // object that actually grabs and processes the RSS data
    CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:nil] autorelease];

    // Create a new Array object to be used with the looping of the results from the rssParser
    NSArray *resultNodes = NULL;

    // Set the resultNodes Array to contain an object for every instance of an  node in our RSS feed
    resultNodes = [rssParser nodesForXPath:@"//item" error:nil];

    // Loop through the resultNodes to access each items actual data
    for (CXMLElement *resultElement in resultNodes) {

        // Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries
        NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];

        // Create a counter variable as type "int"
        int counter;

        // Loop through the children of the current  node
        for(counter = 0; counter < [resultElement childCount]; counter++) {

            // Add each field to the blogItem Dictionary with the node name as key and node value as the value
            [blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
        }

        // Add the blogItem to the global blogEntries Array so that the view can access it.
        [blogEntries addObject:[blogItem copy]];
    }
}

Now I know that probably looks quite confusing but I have tried to add detailed commenting to allow you to follow what It does. Basically it sends a request to the address that you specify and pulls back the response into the rssParser object. Once this is done it loops through the <item< nodes and adds it, along with its children to the global blogEntries Array.

Now that we have a function that will request, read and process a RSS feed into an Array we have to actually call it from somewhere.

Enter “viewDidAppear”!

This function will already be in your file as the template would have created it, but it will be commented out. Remove the comment tags and edit the code to look like the following:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Check if blogEntries has already been filled, if not
    // then send the request
    if([blogEntries count] == 0) {
        // Create the feed string, in this case I have used dBlog
        NSString *blogAddress = @"http://dblog.com.au/feed/";

        // Call the grabRSSFeed function with the above
        // string as a parameter
        [self grabRSSFeed:blogAddress];

        // Call the reloadData function on the blogTable, this
        // will cause it to refresh itself with our new data
        [blogTable reloadData];
    }
}

The above code simply checks to see if the item count in blogEntries is zero, if true then it will call the grabRSSFeed function with the supplied URL and then reload the Table Outlet with the new data. You can change the URL to any valid RSS feed and it will work.

We are getting extremely close to a working application now, just a couple more small changes and we are up and running!

Ones of these is the “numberOfRowsInSection” function, if you have a look in your file you will see it up near the top and it will be returning a static value of zero. What this means is, is that every time the table is reloaded it calls this function to see how many cells it needs to draw. Currently this will always return zero and therefore it will never actually draw anything :(

What you need to do is to make it so when this function is called it returns the count of items in the blogEntries Array, this is very easy to do. Just change the “return 0;” line to the following:

return [blogEntries count];

Now whenever this function is called it will return the correct number of entries, that was easy wasn’t it?

Our final code change will actually generate the cells for the table view, we are just doing a simple cell that shows the title text, but this can be anything including icons, fonts, styles, etc.

Find the “cellForRowAtIndexPath” function in your file, then inside that function find “// Set up the cell” and enter the following code under it.

int blogEntryIndex = [indexPath indexAtPosition: [indexPath length] -1];
[cell setText:[[blogEntries objectAtIndex: blogEntryIndex] objectForKey: @"title"]];

What the above code does is it grabs the index of the item that is being generated and then calls the setText function on the cell with the “title” value of the corresponding entry in blogEntries. You could easily change this to “link”, “pubDate” or any other child node of the node.

Guess what? Its now time to run your application!

7. Running the code for the first time

Make sure that everything is saved and then click Build > Build and Go (Run), you can also press Command + Enter to do the same thing.

You should see the iPhone simulator appear and your application will start up, you should see…nothing!

What? You mean I spent all that time for an application that doesn’t even do anything?

No, no, no, It does do everything that you told it to..BUT, we forgot to link the table display to the blogTable Outlet..doh!

8. Linking the Table in the View to the blogTable Outlet

Double click on the “RootViewController.xib” file in the resources folder in the left hand pane, the “Interface Builder” application will launch with your RootViewController interface in it. You should see something similar to the image below:
Interface Builder

Now in the Main window you will see three icons, the “File’s Owner”, “First Responser” and “Table View”. What we need to do is to Control click and drag from the “File’s Owner” to the “Table View” icons, you will see a blue bar appear as you drag and when you let go over the “Table View” icon a little grey window will appear, see below:

picture-11.png

You will need to select “blogTable” as that is the Outlet we created in our header file. Once you are done you can save the interface and click “Interface Builder”.

9. The Moment of Truth

If you try to Build and Run your application now you should get some results in the screen, for my blog it looked like the following:
Mine Worked!

10. Project Files

Here are the source files for this project: Download the project source files

11. What’s Next?

Well currently you can’t really do much with the application apart from read the headers, I intend to create a series of tutorials outlining how to actually read the rest of the feeds on your phone, how to add multiple feeds and even how to add some simple animation to spruce things up. I will also be taking a look at memory management too as this tutorial hasn’t looked into this at all.

This all depends on time and also on how well this first tutorial goes. But hopefully there will be many more to come.

I hope that you all have a better idea of how to work with the iPhone SDK and also how to get the TouchXML library up and running (it took me a fair while to get my head around it!).

If you have any questions or if you find any bugs please let me know!

Until next time, bye bye!

Popularity: 45% [?]

I sat here for quite some time banging my head against the wall trying to figure out why I was getting a null object reference error for some of my components in a TabNavigator.

After some Googling and hair pulling I found out that only the first tab is actually initialized, while the other tabs only initialized when they were selected…Go figure Adobe to leave this vital point out of the LiveDocs!

Never fear! There is a solution…

On your TabNavigator you need to set the creationPolicy property to all and then all the tabs and their children will be initialized when the application starts.

e.g. <mx:TabNavigator id=”sampleTabNavigator” creationPolicy=”all”>

Hope this saves someone else some time, and hair!

Popularity: 1% [?]

Whilst trekking around the wilderness learning the ins and outs of CakePHP I have compiled a list of helpful CakePHP related sites that have gotten me through some tough times.

After spending so much time finding these resources I thought that I would compile them into a list and publish them.

CakePHP.org

1. Official CakePHP website: The number one source for CakePHP manuals, blogs, API’s, articles and tutorials.

Donutczar.com

2. Donutczar.com: Great information and examples on Helpers in CakePHP 1.2, a really good source for people who want a hand’s on and visual explanation.

Cakebaker

3. cakebaker.42dh.com: Always has new and brilliant ideas for CakePHP applications and offers easy to understand and user-friendly tutorials.

ThinkingPHP

4. ThinkingPHP: Although ThinkingPHP is an all-round PHP information site it also has a very helpful and detailed area dedicated to CakePHP. ThinkingPHP also monitors other popular CakePHP blogs and provides all the information in a common and easy to manage area.

RosSoft

5. Rolsoft.wordpress.com: The RolSoft Blog is an oldie, but a goodie! It has articles on integrating AJAX, speeding up SQL queries in CakePHP and much more. Most of the content is outdated, but it still serves to point people in the right direction and to offer food for thought.

RolSoft

6. Mariano Iglesias: Not only does this blog look amazing, it has buckets of information, everything from CakeFest information, CakePHP tips, framework write-ups and more. This is a a site that you will want to add to your favourites and your blog reader!

Google Group

7. CakePHP Google Group: This is the official Google Code group for CakePHP and it has a large memberbase and has lots of information available. Sometimes it can be a little unwielding to find your way around, but once you have the hang of it you will be flying around in no time.

Tim Trice

8. Tim Trice: This is a great blog that concentrates on articles aimed at the CakePHP beginner. With articles ranging from “What CakePHP can do” through to extending the CakePHP Blog tutorial.

CakePHP.nu

9. CakePHP.nu: Another little CakePHP blog that had a couple of articles that really stood out to me. It is relativly new so there isn’t a great deal of content, but its more like quality over quantity.

In the Kitchen with CakePHP

10. In the Kitchen with CakePHP: This isn’t really a “site” as such but I thought it was worth a mention. “In the Kitchen with CakePHP” is a great tutorial for beginners who need a start to finish walkthrough of CakePHP and its features, it is also useful to have a read before selecting CakePHP as your framework of choice as it goes over many of the key features.

Well for now thats my 10 Helpful resources that got me out of some trouble, if you have any suggestions or comments then please feel free to post them below.

Popularity: 1% [?]

Today is the day that Booksaround, an Australian Online Second hand bookstore is launched.

The CMS for BooksAround was written from scratch and utilises the CakePHP 1.2 framework for everything from inventory management through to payment processing and order fulfillment.

Why CakePHP you ask? Well CakePHP offers a strong yet flexible PHP framework to kickstart application development allowing for a shorter build time and a more affordable project for the client.

The BooksAround CMS allows staff to Add, Edit and Remove books from the database with the ease of integrated Barcode Scanning and automated lookups to ISBN databases such as Amazon and Book Finder. The CMS also allows staff to assign a book source (or Vendor) to each entry in the database and a commission percent, upon sale of a book the application will automatically calculate how much is oweing to the vendor from that sale and apply it to their account.

Payments are processed in real-time through PayPal with their Websites Payments Standard product and the items purchased are automatically marked as sold and Order/Shipping information is sent through to a designated staff member who deals with shipping fulfilment. By using PayPal we were able to completely automate the whole order process from start to finish to ensure that the end-user feels confident in placing an order and that the Site Owner can rest assured that the funds will be cleared before the order is processed.

Nearly every aspect of the site can be modified through the CMS allowing the Site Owner to take complete control of the site and its contents, adding/removing a book, changing vendor details, generating sales reports and even editing page content in real-time are available at their fingertips.

All in all the project was a pleasure to work on and the end result surpassed my expectations on the limited budget, CakePHP once again ame to the party by offering an amazing framework to start with and followed through with a solid, speedy and self contained end product.

So go on over and check out BooksAround.com, there are currently nearly 1,000 books available at a great price and you even receive a 10% discount by ordering online!

-Dean

Popularity: 1% [?]