It is not knowledge, but the act of learning, not possession but the act of getting there, which grants the greatest enjoyment.
Johann Carl Friedrich Gauss (1808), Letter to Bolyai
Xcode 4.2: Where has the MainWindow.xib gone? Creating an empty application - 12 Simple Steps

I remember coming across this problem when I was brand new to Xcode 4.2. Prior to this version, you would create an empty application and a MainWindow.xib file was readily prepared for you. In the new versions of Xcode this is no longer the case. There are some good tutorials around on the web that show give a very comprehensive solution to this problem from scratch. But if you want to skip all that and just get your MainWindow back then there are 12 simple steps you can follow which are significantly more simple than others and produce the same result. However if you want to learn more about the internal structure of your application, the connections, app delegates etc. I recommend you follow the other tutorials.

Below are step-by-step instructions with screen captures; if you're too much of an expert for screen captures, you can skip to here for the summarised steps.

Missing your MainWindow.xib? Let's get her back:

1. Open Xcode 4.2+ (well, dur)

2. Go to File > New > New Project

3. Under 'iOS' select 'Application'. Then you want to select 'Empty Application' and press next.



4. Give your project/app a name. I've named mine after the Ancient Egyptian Pharaoh of the 21st Dynasty, Psusennes I. Enter this name into the 'Class Prefix' as well (if you wish). Press next.

5. Go to File > New > New File

6. Select 'User Interface' under 'iOS' and choose 'Application'. Press next.



7. You'll be prompted to create a .xib file. Name it "MainWindow" (without the .xib extension) and press Create. Your navigator on the left should look something like this:



8. In the interface builder, under 'Objects' select 'App Delegate'. Then, in the Utilities panel choose the Identity Inspector (The third icon from the left). Under 'Custom Class' type in the name of your App Delegate class in the input box. In my case I would enter 'PsusennesAppDelegate'. Under 'Identity', select the Label where it is written 'App Delegate', remove its content and press enter.



You should see that after pressing Enter the App Delegate Object in the left pane will change to '<Your app name> App Delegate'.

9. In the Navigator select your project. In the summary tab, select your project under 'Targets'. Click the 'Main Interface' drop-down menu and enter/select 'MainWindow' and press enter.



10. Now in the Navigator, select your App Delegate interface file (.h). We need to declare the window in the interface file as an outlet so that we can link it in the Interface Builder. Make the changes highlighted below:



11. Select 'MainWindow.xib' in the Navigator. In the interface builder, whilst pressing Ctrl + Click the App Delegate object and drag it the Window object. Then select 'window' in the popup.



12. We'll just test it to make sure everything has worked. Change the background colour of the window to any that you like. Press Run and the iPhone Simulator should launch and the app should open and display your newly painted window.

Steps Summarised

1. Open Xcode 4.2 (no seriously!)
2. Go to File > New > New Project
3. Under 'iOS' select 'Application'. Then you want to select 'Empty Application' and press next.
4. Give your project/app a name. Press next.
5. Go to File > New > New File
6. Select 'User Interface' under 'iOS' and choose 'Application'. Press next.
7. You'll be prompted to create a .xib file. Name it "MainWindow" (without the .xib extension) and press Create.
8. In the interface builder, under 'Objects' select 'App Delegate'. Then, in the Utilities panel choose the Identity Inspector (The third icon from the left). Under 'Custom Class' type in the name of your App Delegate class in the input box. Under 'Identity', select the Label where it is written 'App Delegate', remove its content and press enter.
9. In the Navigator select your project. In the summary tab, select your project under 'Targets'. Click the 'Main Interface' drop-down menu and enter/select 'MainWindow' and press enter.
10. Now in the Navigator, select your App Delegate interface file (.h). We need to declare the window in the interface file as an outlet so that we can link it in the Interface Builder. (You may need to scroll up for the screen capture for this one!)
11. Select 'MainWindow.xib' in the Navigator. In the interface builder, whilst pressing Ctrl + Click the App Delegate object and drag it the Window object. Then select 'window' in the popup.
12. Test it to make sure everything has worked. Change the background colour of the window to any that you like. Press Run and the iPhone Simulator should launch and the app should open and display your newly stained window.


Hope that helps anyone looking for a quick and simple solution.


Tutorial: A simple method for displaying the number of users online and the page they are browsing (PHP/MySQL)

This tutorial will demonstrate how you can create a very simple 'Users online' script that will tell you how many users are browsing your website and what page they are on.

First we create a table:

CREATE TABLE IF NOT EXISTS `users_online` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ip` varchar(20) NOT NULL,
`timevisited` varchar(20) NOT NULL,
`page` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

You can either execute this in your preferred MySQL administration tool (e.g. phpMyAdmin), or execute it in PHP: mysql_query($create); where $create is equal to the above SQL query. The timevisited column will take a timestamp (i.e. time()) in case you're wondering.

Updating the list

Now we'll create a function named usersOnline($time_span) that takes an input $time_span, which is the amount of minutes you wish to keep the user in the database or 'list' before they are removed. A realistic duration would be around 5-10 minutes.

function usersOnline($time_span) {

$time_criterion = time()-($time_span*60);
$clean = mysql_query("DELETE FROM `users_online` WHERE `timevisited` < '$time_criterion'") or die (mysql_error());
}

The function begins by taking the time span and converting it into a criterion that will be used for comparison in the $clean query ($time_span*60 simply converts the time span into seconds). Then the $clean query deletes any rows in the users_online table that are older than the specified time span.

function usersOnline($time_span) {

$time_criterion = time()-($time_span*60);
$clean = mysql_query("DELETE FROM `users_online` WHERE `timevisited` < '$time_criterion'") or die (mysql_error());

$ip_address = fetchIpAddress();
$check = mysql_query("SELECT * FROM `users_online` WHERE `ip` = '$ip_address'") or die (mysql_error());
}

Next we grab the user's IP address and check if they are already in the database. The function fetchIpAddress() is defined below:


function fetchIpAddress() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip_address=$_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip_address=$_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip_address=$_SERVER['REMOTE_ADDR'];
}
return $ip_address;
}

The function checks for the users true IP address, so if that user is using a proxy it will grab that IP address.

We then store the number of rows returned by the $check query in $rows, define the current timestamp and the page the user is on (the page's path rather).

function usersOnline($time_span) {

$time_criterion = time()-($time_span*60);
$clean = mysql_query("DELETE FROM `users_online` WHERE `timevisited` < '$time_criterion'") or die (mysql_error());

$ip_address = fetchIpAddress();
$check = mysql_query("SELECT * FROM `users_online` WHERE `ip` = '$ip_address'") or die (mysql_error());
$rows = mysql_num_rows($check);

$current_timestamp = time();
$page = mysql_real_escape_string($_SERVER['REQUEST_URI']);
}

Next step is to handle the cases where the user is or is not in the database. If the user is not in the database, then we insert a new row with the details defined above. If the user is in the database, we simply update the existing row with the page the user is on $page and the new (updated) timestamp $current_timestamp:

function usersOnline($time_span) {

$time_criterion = time()-($time_span*60);
$clean = mysql_query("DELETE FROM `users_online` WHERE `timevisited` < '$time_criterion'") or die (mysql_error());

$ip_address = fetchIpAddress();
$check = mysql_query("SELECT * FROM `users_online` WHERE `ip` = '$ip_address'") or die (mysql_error());
$rows = mysql_num_rows($check);

$current_timestamp = time();
$page = mysql_real_escape_string($_SERVER['REQUEST_URI']);
if ($rows == 0) {
$insert = mysql_query("INSERT INTO `users_online` (`ip`, `timevisited`, `page`) VALUES ('$ip_address', '$current_timestamp', '$page')") or die (mysql_error());
} else {
$update = mysql_query("UPDATE `users_online` SET `timevisited` = '$current_timestamp', `page` = '$page' WHERE `ip` = '$ip_address'") or die (mysql_error());
}
}

It is very important to escape the $page variable as you would otherwise be vulnerable to SQL injection when executing your query, and so we use mysql_real_escape_string() to do so.

Displaying the list

Now we want to show what's in our table and we do so by creating a function called showUsersOnline($show_list) which takes the input $show_list, giving you the option to either show the number of users online, or show both the number and additional information such as IP address, page, time etc.

We begin by printing the number of users that are online (rows returned by the $check query):

function showUsersOnline($show_list) {
$check = mysql_query("SELECT * FROM `users_online` ORDER BY `timevisited` DESC") or die (mysql_error());
$rows = mysql_num_rows($check);

echo "Users online: $rows";
}

Next we display a list of users that are online and what page they are on:

function showUsersOnline($show_list) {
$check = mysql_query("SELECT * FROM `users_online` ORDER BY `timevisited` DESC") or die (mysql_error());
$rows = mysql_num_rows($check);

echo "Users online: $rows";
if ($show_list) {
$count=1;
while ($useronline = mysql_fetch_array($check)) {
echo "<br />• $count. ($useronline[ip]) Browsing page: <a href=\"$useronline[page]\">$useronline[page]</a>";
$count++;
}
}
}

We store the data in each row in an array $useronline and loop through the results. The order of results is really up to you; in this example I've ordered them by timevisited DESC - in order of the most recent visit/activity (which would always be yourself). $count is simply an increasing counter to number the results/list, this can be done in many other ways and you don't necessarily have to do it like I have done here. You'll notice that if ($show_list) precedes the part of the code that shows the list; with this function you will have the option to specify whether you want the list to be shown or not. For example, if you would prefer that guests/normal users can only see the number of users online and not the list (as this contains private information such as the IP address), then you would call showUsersOnline(0);. If the user is an administrator with certain access privileges, then you would call showUsersOnline(1);. Of course you could just omit the IP address from the list in the function above and display it for both administrators and normal users.

You might be thinking, well what if $check returns zero results? Wouldn't I need to place an if statement before displaying the list of users online? Well in the above case, no. In order to view the list, a user must be browsing on the website and so there will always be a row in the users_online table.

So we end up with three functions, ideally placed in some sort of functions file:

<?php
function usersOnline($time_span) {

$time_criterion = time()-($time_span*60);
$clean = mysql_query("DELETE FROM `users_online` WHERE `timevisited` < $time_criterion") or die (mysql_error());

$ip_address = fetchIpAddress();
$check = mysql_query("SELECT * FROM `users_online` WHERE `ip` = '$ip_address'") or die (mysql_error());
$rows = mysql_num_rows($check);

$current_timestamp = time();
$page = $_SERVER['REQUEST_URI'];
if ($rows == 0) {
$insert = mysql_query("INSERT INTO `users_online` (`ip`, `timevisited`, `page`) VALUES ('$ip_address', '$current_timestamp', '$page')") or die (mysql_error());
} else {
$update = mysql_query("UPDATE `users_online` SET `timevisited` = '$current_timestamp', `page` = '$page' WHERE `ip` = '$ip_address'") or die (mysql_error());
}
}

function fetchIpAddress() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip_address=$_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip_address=$_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip_address=$_SERVER['REMOTE_ADDR'];
}
return $ip_address;
}

function showUsersOnline($show_list) {
$check = mysql_query("SELECT * FROM `users_online` ORDER BY `timevisited` DESC") or die (mysql_error());
$rows = mysql_num_rows($check);

echo "Users online: $rows";
if ($show_list) {
$count=1;
while ($useronline = mysql_fetch_array($check)) {
echo "<br />• $count. ($useronline[ip]) Browsing page: <a href=\"$useronline[page]\">$useronline[page]</a>";
$count++;
}
}
}
?>

You would then include this in your main page (before the main body) after establishing a connection to your database, and then if you wish, display the results. Below is a very basic example:

<?php
include_once 'config.php'; //This file would contain the variables needed to connect to the database with $link, below
include_once 'functions.php'; //We include the functions we have created

$link = mysql_connect($server, $db_user, $db_pass)or die ("Could not connect to mysql because ".mysql_error());
mysql_select_db($database)or die ("Could not select database because ".mysql_error());

usersOnline(5); //We call the usersOnline function with a time span of 5 minutes

showUsersOnline(1); //Show the number of users online, and the list of users

mysql_close($link);
?>

That ends this tutorial. As always if you notice any errors or have anything to say/ask, drop me a comment below.

Update: I was just reading over this tutorial and thought that it may be better to place $clean (and if you want, $time_criterion) at the end of the function - that way if the user (their IP) exists in the database, a single update is performed rather than deleting the user and inserting a new row; decreasing overall execution time of the function.


SmartPlayer is 'Ready for Sale' and free for today

After going back and forth with Apple about changing my iTunes Connect or 'Entity' Address, the app is finally ready for sale.

For those of you wondering how long it took for Apple to change the address; I scanned a copy of my driving license (has to be some sort of official document with your new address on it) and then called them to let them know I'd sent it. There and then my address was changed on iTunes connect and the changes took immediate effect - the whole process took about roughly 1-2 hours.

The app is free for today so feel 'free' to purchase it! (sorry)

Purchase SmartPlayer for iOS


Tutorial: Ordering and displaying your news articles 'archive' by year and month (PHP/MySQL)

I thought I should start making a habit of posting tutorials on the site. The web is full of great websites where people have taken the time to teach others what they have learnt and I feel it''s always good to 'pay it forward'.

My first tutorial will show you how to display news articles (with a recorded timestamp) stored in your MySQL database in reverse chronological order, ordering them by year and then month (newest -> oldest). So the end result should look very similar to the one on this website:

2012
January
• Happy new year!

2011
December
• Merry christmas
November
• Guy Fawkes night

2010
April
• April fools day!

I'll assume here that one of the columns in your MySQL table (we'll name it news) contains the timestamp recorded at the time the news article was created, for the sake of simplicity we'll call this column timestamp. Another assumption I'm making is that you have established a connection to your MySQL database in your script.

We begin by making a query to grab the timestamp of the newest news article in the database:

$get_newest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp DESC LIMIT 1") or die (mysql_error());

If you have an id column in your database which is a primary key and is automatically incrememnted, you may choose to change the above query to ORDER BY id DESC LIMIT 1, it doesn't matter which you choose as they will both grab the newest article.
Next we want to check if in fact the database has any news articles yet, useful for any new websites being set up:

$rows = mysql_num_rows($get_newest);

if ($rows == 0) {
echo 'There are no news articles in the archive';
}

If the query returns zero rows then the database is empty. If it isn't empty we want to begin retrieving news articles and ordering them in the way that we want.

Similarly we grab the timestamp of the oldest news article:

$get_newest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp DESC LIMIT 1") or die (mysql_error());
$rows = mysql_num_rows($get_newest);

if ($rows == 0) {
echo 'There are no news articles in the archive';
} else {
$get_oldest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp ASC LIMIT 1") or die (mysql_error());
$data_oldest = mysql_fetch_array($get_oldest);
$data_newest = mysql_fetch_array($get_newest);
}

We extract the information from both the newest and oldest queries store it in two separate arrays $data_newest, $data_oldest.

Next we get the year of both the oldest and newest dates and create a temporary variable $temp_year that we'll use to scan through from the newest year to the oldest:

$get_newest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp DESC LIMIT 1") or die (mysql_error());
$rows = mysql_num_rows($get_newest);

if ($rows == 0) {
echo 'There are no news articles in the archive';
} else {
$get_oldest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp ASC LIMIT 1") or die (mysql_error());
$data_oldest = mysql_fetch_array($get_oldest);
$data_newest = mysql_fetch_array($get_newest);

$newest_year = date("Y",$data_newest[timestamp]);
$oldest_year = date("Y",$data_oldest[timestamp]);
$temp_year = $newest_year;
}

We've used the timestamp of the news article in the date() function to retrieve the year. The temporary year $temp_year has been set to the newest year as the order we require is newest -> oldest.

Now we want to loop through all years (between and including the newest and oldest years):

$get_newest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp DESC LIMIT 1") or die (mysql_error());
$rows = mysql_num_rows($get_newest);

if ($rows == 0) {
echo 'There are no news articles in the archive';
} else {
$get_oldest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp ASC LIMIT 1") or die (mysql_error());
$data_oldest = mysql_fetch_array($get_oldest);
$data_newest = mysql_fetch_array($get_newest);

$newest_year = date("Y",$data_newest[timestamp]);
$oldest_year = date("Y",$data_oldest[timestamp]);
$temp_year = $newest_year;


for($temp_year; $temp_year >= $oldest_year; $temp_year--) {
echo "<b>$temp_year</b><br />";
}
}

Next we need to insert another loop that scans through each month of each year and grab the news articles belonging to that period and display them:

$get_newest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp DESC LIMIT 1") or die (mysql_error());
$rows = mysql_num_rows($get_newest);

if ($rows == 0) {
echo 'There are no news articles in the archive';
} else {
$get_oldest = mysql_query("SELECT timestamp FROM news ORDER BY timestamp ASC LIMIT 1") or die (mysql_error());
$data_oldest = mysql_fetch_array($get_oldest);
$data_newest = mysql_fetch_array($get_newest);

$newest_year = date("Y",$data_newest[timestamp]);
$oldest_year = date("Y",$data_oldest[timestamp]);
$temp_year = $newest_year;


for($temp_year; $temp_year >= $oldest_year; $temp_year--) {
echo "<b>$temp_year</b><br />";

for($month=12; $month >= 1; $month--) {

$check = mysql_query("SELECT * FROM news WHERE MONTH(FROM_UNIXTIME(timestamp))='$month'
AND YEAR(FROM_UNIXTIME(timestamp))='$temp_year' ORDER BY timestamp DESC") or die (mysql_error());
$check_rows = mysql_num_rows($check);

if ($check_rows == 0)
continue;

echo "<br /><i>".date("F", mktime(0, 0, 0, $month))."</i>";

while($data = mysql_fetch_array($check)) {
echo '<br />• <a href="yourwebsite.com/posts/read/id-'.$data[timestamp].'">'.$data[title].'</a>';
}
}
}
}

The for loop begins with December (12), through to January (1) as specified by the condition $month >= 1. After each iteration, 1 is subtracted from $month ($month--) and the process continues. Inside each loop a query is executed to check if there are any news articles associated with that month and year, and if there isn't $check_rows will return zero and the command continue; is executed which skips the rest of the current iteration, deducts 1 from the month and checks again for any news articles for the next month/year. There's something very convenient going on in the $check query; the combination of MONTH() or YEAR() with FROM_UNIXTIME(), which are all MySQL functions, allows us to set a criteria for the year and month of the news articles we want. If there are any news articles for that month/year then we first print the name of that month using date("F", mktime(0, 0, 0, $month)) which takes the month in digit-form and returns the month name (string).

Finally we loop through each row returned by the query $check and store it's information in an array $data. Inside the loop we print out the information we want to display; in this tutorial I've chosen to display only the title of the news article (and a hyperlink to that article) under each month/year.

Chronological order

Some may want to show their articles in chronological order (oldest -> newest) and this only requires tweaks in two locations in the code that is the two `for` loops. For the first loop, rather than starting with newest year, we start with the oldest:

    $temp_year = $oldest_year;

for($temp_year; $temp_year <= $newest_year; $temp_year++) { ... }

Furthermore we change the condition so that iterations continue for when the year is less than or equal to the newest year in the archive. Additionally $temp_year is incremented to proceed to the next year up. Note: you could very easily omit the first line and just have: for($temp_year=$oldest_year; $temp_year <= $newest_year; $temp_year++) { ... }, but I've broken it down for clarity.

For the loop concerning the month the adjustments are very similar; we begin with January (1) and iterate through to December (12) and increase $month by 1 after each iteration:

        for($month=1; $month <= 12; $month++) { ... }

That ends the tutorial and hopefully I haven't made any errors. I feel this method is transparent and very easy to grasp but of course this is one of many ways you can produce this kind of script.

Some may argue that for a database with a large amount of data, executing a query repeatedly in a for loop will increase overall page load-time. However I don't think is too much of an issue as I've not experienced any problems and very rarely does one list their entire archive on a single page (if very large) without adding some sort of pagination to control it.

If you have any questions/suggestions feel free to leave a comment.


Website launched, no Twitter, and my first iOS application submitted to the App Store

I started the website roughly a week ago and it appears to be coming along quite nicely, although some pages still need some attention. I'm not big on the idea of twitter for personal use (maybe in the future), but I'd be naive to not to have an account when entering the world of development and programming. Normally I'd go for a simple username like @shaddeen but it's taken and so are all other possible permutations; and the worst thing is, they're not even being used! I've contacted twitter about this so fingers crossed. Perhaps one of the users will stumble across this post and offer their twitter account in exchange for a free copy of SmartPlayer?

SmartPlayer for iOS: I'm all about aesthetics and if there's a 'prettier' product that servers the exact same functionality as another lower-priced 'ugly' version, I'll certainly opt for the former - even if it means I lose a feature or two. Now, Apple's music application is exactly what people need to listen to music - you can browse your library, play songs, shuffle, play, pause, play-pause, pause-play, pause-play-pause, etc. but there's just, at least for me, something missing in terms of appearance. I'm mainly talking about the 'Now Playing' view, where the artwork and controls are displayed. This is where the idea of making SmartPlayer came from; I wanted to create an App that looked great and makes the iOS music experience a little different, good different I hope. I originally began with the Light theme, then after a night of using the app I decided to add a Dark one - I was in bed, lights off, listening to an album and decided and I wanted to change it to something more easy listening. Unlocked my iPhone and had what seemed like the Sun right in front of my face, hence the Dark theme that's easier on the eyes.

Looks aside, SmartPlayer features a built-in fading out sleep timer (inside the app) and ironically, Twitter integration. Maybe some day I'll be able to use this great feature. So the idea is that you can tweet what you play, a nice little feature (you're also able to change the prefix of the tweet in the Settings).

So now we play the waiting game...

...waiting game sucks, let's play hungry hungry hippos!

Update: for now, @shaddeen_


Profile
Shad Deen MEng
London, United Kingdom
Developer


SmartPlayer for iOS
SmartPlayer for iOS


Read about Iraq & Kurdistan's first psychological horror film, shooting this summer.


...you've just found some serious talent.


Terms of use • Website Designed & Programmed by Shad Deen • Copyright © 2011-12, All Rights Reserved.