Recent Posts
iOS: Sliding images on and off the screen using one UIImageView


Here is a rather elegant and simple method for achieving this:

self.yourImageView.image = [UIImage imageNamed:@"yourNewImage.png"];
CATransition *animation = [CATransition animation];
[animation setDuration:1.0]; //Animate for a duration of 1.0 seconds
[animation setType:kCATransitionPush]; //New image will push the old image off
[animation setSubtype:kCATransitionFromRight]; //Current image will slide off to the left, new image slides in from the right
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[self.yourImageView layer] addAnimation:animation forKey:nil];

Here, the first/current image is retained whilst the new image is sliding in.

The CATransition class is from the QuartzCore framework so you'll need to link this to your project and import it into your class (#import <QuartzCore/QuartzCore.h>).

Latest SmartPlayer developments (v2.x)

It's been a few months since my last post. Amongst other things I've been rather busy with the new version of the app [App Store]. It's a big step up from the first version with a completely new UI and a lot of new features. Notably the ones listed below:

Last.fm Integration

I've been a Last.fm user for years and haven't yet found an app (that I'm happy with), which integrates scrobbling, is feature-rich and looks good. After receiving a few requests for this feature I decided to take some extra time to work on it. Last.fm's API documentation is very clear but I initially had problems authenticating the user's session. So I did a bit of searching and came across the official Last.fm application source file uploaded to GitHub by Sam Steele (aka c99koder); with this I was able to correctly integrate the scrobbling feature. So if you're reading this Sam, thanks a bunch, and if you're ever in London, I'll buy you a drink.

New and Customisable UI

The most obvious change is the UI. Backgrounds can be changed (a selection included in the app or you can select one from your photo library), and there is a choice of artwork styles and transitions.

Artwork Mode


Cover-flow is cool, but I prefer the linear look of SmartPlayer's 'Artwork Mode'. Some users have asked for a landscape mode, so this works in both portrait and landscape. It uses iCarousel, a class created by Nick Lockwood; an excellent piece of work which was very easy to implement and modify to suit the app.

Quick Playlist and Track Queueing

There's now an editable 'Quick Playlist' (self-explanatory), and a new Track Queueing feature: slide and flick individual tracks or albums to add them to the queue of your 'Now Playing' list. This is one of my favourite features, very convenient.

For a full list of features see the app's page here.

SmartPlayer Free

I find Ads in apps very annoying and feel it's a bit of a con when you pay for the full version of an app and the only thing you gain is the removal of Ads. There are no Ads in the free version of SmartPlayer [App Store], only limited features. You're paying for new features and that's all.

For now, I don't have any plans to make any more significant additions to the app. I may add a few small things in the future, so if your suggestions aren't too demanding, please do contact me. Of course, I'll continue to submit updates to fix any bugs that might appear as the new versions of iOS roll out.

Link: SmartPlayer (Full)
Link: SmartPlayer (Free)

Promo: SmartPlayer free giveaway (App Store Promo-codes) [Updated]

I'm feeling generous tonight and giving away App Store promo-codes to purchase SmartPlayer for free. On a first-come, first-serve basis. To get a promo-code simply leave a comment below with your email address (I'll be emailing the code to you). If you prefer not to publicise your email address, enter it in the 'email address' field in the comment form (only I will able to see it).

I'll update this post once all codes have been claimed.

Promo-codes remaining: all gone

Update 8th Feb: The app is free for 24 hours, enjoy!

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 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 on the web that 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 don't think you'll need them, you can skip to here for the summarised steps.

1. Open Xcode 4.2+

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
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.

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

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.

Profile
Shad Deen MEng
London, United Kingdom
Developer

SmartPlayer for iOS


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


Latest Activity
Promo: SmartPlayer free giveaway (Ap.. 31/01/12
Terms of use • Website Designed & Programmed by Shad Deen • Copyright © 2011-12, All Rights Reserved.