Microsoft Azure – Storage – Part 3 – List the contents of the container with a .NET application

In the second part of the Azure Storage series we have developed a .Net application that can create a Microsoft Azure storage  container and upload files into it. Today we will extend the functionality of our application to list the files in the container.

List the files in the container

First let’s create a class that represents the Azure Blob. This way we can isolate our console application from the Azure Storage system, so in the future it can work with any cloud storage systems.

Add a file to the Azure_Helper project to store enumerations

  • Right click the Azure_Helper project and select Add -> Class
  • Name the class Enums
  • Add an enumeration outside of the class definition. The file should look like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace nsAzure_Helper {

    public class Enums {
    }

    public enum ItemType {
        undefined
        , BlobDirectory
        , BlockBlob
        , PageBlob

    }
}

Add a class to the Azure_Helper to represent a file or directory in the cloud

  • Right click the Azure_Helper project and select Add -> Class
  • Name the class CloudItem
  • To make the class public enter the word public in front of the word class
public class CloudItem
  • Add public properties to the class. The class definition should look like this:
public class CloudItem {

    public long Length { get; set; }
    public Uri Uri { get; set; }
    public ItemType Itemtype { get; set; }

}
  • Open the Azure_Helper.cs file in the Azure_Helper project
  • Add a new method to list the content of the container
/// <summary>
/// Returns the list of cloud items in the container
/// </summary>
/// <param name="sContainerPath"></param>
/// <returns></returns>
public List<CloudItem> GetContainerItems(string sContainerPath) {

    List<CloudItem> itemList = null;

    // Create the blob client. 
    CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

    // Retrieve reference to a previously created container.
    CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

    if (null == container) {
        // No container found
        return itemList;
    }

    // Create an instance of the item list
    itemList = new List<CloudItem>();

    // Loop over items within the container and output the length and URI.
    foreach (IListBlobItem item in container.ListBlobs(null, false)) {

        // Create a new instance of the Cloud Item
        CloudItem cloudItem = new CloudItem();

        if (item.GetType() == typeof(CloudBlockBlob)) {
            // This is a Block Blob

            CloudBlockBlob blob = (CloudBlockBlob)item;

            cloudItem.Itemtype = ItemType.BlockBlob;
            cloudItem.Length = blob.Properties.Length;
            cloudItem.Uri = blob.Uri;

        } else if (item.GetType() == typeof(CloudPageBlob)) {
            // This is a Page Blob

            CloudPageBlob pageBlob = (CloudPageBlob)item;

            cloudItem.Itemtype = ItemType.PageBlob;
            cloudItem.Length = pageBlob.Properties.Length;
            cloudItem.Uri = pageBlob.Uri;

        } else if (item.GetType() == typeof(CloudBlobDirectory)) {
            // This is a Directory

            CloudBlobDirectory directory = (CloudBlobDirectory)item;

            cloudItem.Itemtype = ItemType.BlobDirectory;
            cloudItem.Uri = directory.Uri;

        }

        // Add the item to the list
        itemList.Add(cloudItem);

    }

    return itemList;

}

The method above returns a list of Cloud Items.

Let’s call the method from our Console Application

  • Open the Program.cs file in the Azure_ConsoleApplication project
  • Add the following code to the existing lines
// Get the list of items in the Container
List<CloudItem> itemList = azureHelper.GetContainerItems(sContainerPath);
if (null != itemList){

    foreach (CloudItem item in itemList){

        if (ItemType.BlockBlob == item.Itemtype) {

            Console.WriteLine("Block blob of length {0}: {1}", item.Length, item.Uri);

        } else if (ItemType.PageBlob == item.Itemtype) {

            Console.WriteLine("Page blob of length {0}: {1}", item.Length, item.Uri);

        } else if (ItemType.BlobDirectory == item.Itemtype) {

            Console.WriteLine("Directory: {0}", item.Uri);
        }

    }
}

Console.WriteLine("Press a key to exit");
Console.Read();

The Program.cs file should look like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using nsAzure_Helper;

namespace Azure_ConsoleApplication {
	class Program {
		static void Main(string[] args) {

			// Create an instance of the Azure Helper
			Azure_Helper azureHelper = new Azure_Helper();

			string sContainerPath = "test1";
			bool bMakeContainerPublic = true;
			string sBlobName = "blob1";
			string sSourceFilePath =  @"D:\MediaFiles\Audio\Music.wav";

			// Create a public container
			azureHelper.CreateContainer(sContainerPath, bMakeContainerPublic);

			// Upload an audio file
			azureHelper.UploadFile(sContainerPath, sBlobName, sSourceFilePath);

			// Get the list of items in the Container
			List itemList = azureHelper.GetContainerItems(sContainerPath);
			if (null != itemList){

				foreach (CloudItem item in itemList){

					if (ItemType.BlockBlob == item.Itemtype) {

						Console.WriteLine("Block blob of length {0}: {1}", item.Length, item.Uri);

					} else if (ItemType.PageBlob == item.Itemtype) {

						Console.WriteLine("Page blob of length {0}: {1}", item.Length, item.Uri);

					} else if (ItemType.BlobDirectory == item.Itemtype) {

						Console.WriteLine("Directory: {0}", item.Uri);
					}

				}
			}

			Console.WriteLine("Press a key to exit");
			Console.Read();

		}

	}
}

In the next article we will learn how to download files from the Microsoft Azure storage.

Microsoft Azure – Storage – Part 2 – Upload files with a .NET application


In the first part of the Azure Storage series we have created a Microsoft Azure storage in the “cloud”. Now we will create a C# application to upload, list and download files.

Create a Blank  Solution

  • In the File menu select New -> Project

visual studio blank solution

Add a new Console Application project to the solution

  • In the Solution Explorer right click the solution and select Add -> New Project
  • Name the project Azure_ConsoleApplication

visual studio console application

Add  a Class Library project to the solution

  • In the Solution Explorer right click the solution and select Add -> New Project
  • Name the project Azure_Helper

visual studio class library

Set the namespace of the helper project to nsAzure_Helper

When you create a new project Microsoft Visual Studio sets the default namespace to the same as name of the project. In .NET you cannot create a class with the same name as the name space of its project. For clarity I usually name the main class of the project after the name of the project, so I have to change the default namespace of the project.

  • Right click the Azure_Helper project and select Properties
  • On the left side select the Application tab
  • Set the Default namespace to nsAzure_Helper
  • Press CTRL-S on the keyboard to save the project file
    azure set the middletier namespace

Add a new class to the Azure_Helper class library

  • In the Solution Explorer delete automatically created the Class1.cs file
  • Right click the Azure_Helper project and select Add -> Class
  • Name the new class Azure_Helper and click the Add button
    azure middletier add new class

Add an Application Configuration File to the Console Application to store the Azure connection string

  • In the Solution Explorer right click the console application and select Add -> New Item

visual studio app config

  • When the new App.config file opens add lines to it, so it looks like this:
<configuration>
  <appSettings>
      <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=[AccountName];AccountKey=[AccountKey]" />
  </appSettings>
</configuration>

Where
[AccountName] is the Storage Account Name
[AccountKey] is the Primary key of the storage account

Add the Azure framework to the class library

  • Right click the class library and select Manage NuGet Packages…
  • In the upper right corner enter WindowsAzure.Storage
  • Select the Windows Azure Storage package and click Install

azure nuget windows azure storage

  • In the pop-up window click I Accept to download the rest of the necessary libraries.

azure nuget windows azure storage dependencies

Connect to the Azure storage

  • Open the Azure_Helper class in the Azure_Helper project
  • Add using statements to the Azure_Helper class to reference the Azure SDK


using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

Add a reference to the System.Configuration assembly to access the App.config file

  • In the Solution Explorer right click the References folder of the Azure_Helper project and select Add Reference
  • Select Assemblies, Framework, System.Configuration and click the OK button
    visual studio add reference system configuration
  • Add a using statement to the Azure_Helper class to access the app.config file

using System.Configuration;

  • Add an instance variable to the Azure_Helper class to get the connection string from the config file


CloudStorageAccount _storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);

Your Azure_Helper class should look like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

using System.Configuration;

namespace nsAzure_Helper
{
    public class Azure_Helper
    {
        // Retrieve storage account from connection string.
        CloudStorageAccount _storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);

    }
}

Create a storage container

Add a new method to the Azure_Helper class

  • Add a method to your Azure_Helper class to create a container in the Azure Storage account
public void CreateContainer(string sContainerPath) {

	// Create the blob client.
	CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

	// Retrieve a reference to a container. 
	CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

	// Create the container if it doesn't already exist.
	container.CreateIfNotExists();

}

Call the CreateContainer method

Add a reference to the middle tier

  • In the Solution Explorer right click the References folder of the console application project and select Add Reference
  • On the left side of the pop-up window click Solution, Projects, and select to the middle tier project
    azure add reference to middletier

Open the Program.cs file of the console application

  • Add a using statement to the Program.cs class
using nsAzure_Helper;
  • Instantiate the Azure Halper, call the CreateContainer method. Your Program.cs class should look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using nsAzure_Helper;

namespace Azure_ConsoleApplication {
    class Program {
        static void Main(string[] args) {

            // Create an instance of the midle tier
            Azure_Helper azureHelper = new Azure_Helper();

            string sContainerPath = "test1";
            string sBlobName = "blob1";

            // Create a container
            azureHelper.CreateContainer(sContainerPath);

        }
    }
}

Test the application

When you run the application the “test1” container should be created. To verify the result open the Windows Azure management console at https://manage.windowsazure.com/#Workspaces/All/dashboard

  • On the left side select All Items
  • Click the storage account
    azure select storage account
  • Click the Containers link
    azure select containers
  • Click the name of the container to view the files
    azure container list
  • We just created the container, so it is empty
    azure empty container

 

 

You can also use any Azure management tools. The first part of the Azure Storage series contains a link to a list of Azure management tools.

 

Add an option to make the container public

When you create the container only the account owner can access the files in the container. We will add a boolean argument to the CreateContainer method, so the caller of the method can make the container public. Anyone on the Internet can see the public files, but you need the access key to modify and delete them.

  • Change the signature of the CreateContainer method in the Azure_Helper class to
    public void CreateContainer(string sContainerPath, bool bMakeItPublic) {
  • Add the following lines to the end of the method before the closing curly bracket
    // Make the container public if requested
    if (bMakeItPublic) {
    
    	container.SetPermissions( new BlobContainerPermissions { PublicAccess =	BlobContainerPublicAccessType.Blob});
    
    }

The CreateContainer method should look like this

public void CreateContainer(string sContainerPath, bool bMakeItPublic) {

	// Create the blob client.
	CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

	// Retrieve a reference to a container. 
	CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

	// Create the container if it doesn't already exist.
	container.CreateIfNotExists();

	// Make the container public if requested
	if (bMakeItPublic) {

		container.SetPermissions( new BlobContainerPermissions { PublicAccess =	BlobContainerPublicAccessType.Blob});

	}

}

Change the call to the method in the Program.cs class of the Azure_ConsoleApplication project

  • Open the Program.cs file in the Azure_ConsoleApplication project
  • Add true as  the second attribute to the call to the CreateContainer method to create a public container
// Create a public container
azureHelper.CreateContainer(sContainerPath, true);

  Upload a file to the container

The files in the container are called blobs (binary large objects), because those can be any type of files: documents, pictures, videos, music. There are two methods to store these blobs: as blocks or pages. in this example we will store our files a block blobs.

 

Create a new method in the Azure_Helper class:

public void UploadFile(string sContainerPath, string sBlobName, string sSourceFilePath) {

	// Create the blob client.
	CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();

	// Retrieve reference to a previously created container.
	CloudBlobContainer container = blobClient.GetContainerReference(sContainerPath);

	// Retrieve reference to a blob named "myblob".
	CloudBlockBlob blockBlob = container.GetBlockBlobReference(sBlobName);

	// Create or overwrite the "myblob" blob with contents from a local file.
	using (var fileStream = System.IO.File.OpenRead(sSourceFilePath)) {
		blockBlob.UploadFromStream(fileStream);
	}

}

  Call the UploadFile method from the console application

  • Open the Program.cs file in the console application and modify the Main method to look like this
    static void Main(string[] args) {
    
        // Create an instance of the Azure Helper
        Azure_Helper azureHelper = new Azure_Helper();
    
        string sContainerPath = "test1";
        bool bMakeContainerPublic = true;
        string sBlobName = "blob1";
        string sSourceFilePath =  @"D:\MediaFiles\Audio\Music.wav";
    
        // Create a public container
        azureHelper.CreateContainer(sContainerPath, bMakeContainerPublic);
    
        // Upload an audio file
        azureHelper.UploadFile(sContainerPath, sBlobName, sSourceFilePath);
    
    }

 Test the application

If you run the application now the file should be uploaded to the Azure storage.

  • Refresh the Windows Azure management page to see the blob in the container
    azure container list of blobs

In the next article we will extend our application to list the contents of the Container.

Microsoft Azure – Storage – Part 1 – Getting started

Sign up for Microsoft Azure

To create a Microsoft Azure storage account first create a Microsoft Azure account. If you are an MSDN subscriber you may open an account without using a credit card and limit your usage to the MSDN provided $150 free monthly allowance.

Once you created your Microsoft Azure account open the Azure Management Console at

https://manage.windowsazure.com/#Workspaces/All/dashboard

Create a storage account

  • On the left side of the page select Storage
  • Click Create a storage account
  • Enter the first part of the URL for your storage
  • Select the region where you want to create the storage
  • If you want to save money for your test environment uncheck Enable Geo-Replication
  • Click the Create storage account at the bottom

Get the Storage Access Keys

To access your storage area you need to use the 512 bit storage access keys. Azure already generated them:

  • In the Azure Management Portal select All Items on the top of the left side
  • Select the storage account you want to administer
  • At the bottom of the page click Manage Access Keys
    azure storage access keys
  • Copy the primary and secondary key from the pop-up window

 

 

 Get a Cloud Storage Management tool

Microsoft did not develop a management tool for its cloud storage solution, so you need to shop around an find a tool you trust. The MSDN web site contains an outdated list of Windows Azure Storage Explorers at

http://blogs.msdn.com/b/windowsazurestorage/archive/2010/04/17/windows-azure-storage-explorers.aspx

One new tool is Cloud Combine. It has a 30 day free trial period and a $9.99 price with unlimited lifetime usage and updates. You can get it at http://www.gapotchenko.com/cloudcombin This tool can also manage your Amazon S3 storage account.

 

In the next article we will create a .Net application to access the Azure Storage.

 

 

 

Extend the iPhone view in Xcode

When you design an iPhone, iPad view in the Xcode Builder and place a Scroll View on the View Controller you can make the page larger than the physical size of the screen of the device. To see the whole view set the size of the View.

  • Open the Story Board in Xcode
  • Shift Control Click the view to display the list of objects under the mouse
  • Select the View Controller
    xcode select layers with shift control click controller
  • Open the Utilities view
  • Select the Attributes inspector
  • Set the Size to Freeform
    xcode set controller size freeform
  • Shift Control click the view again
  • Select the View
    xcode select layers with shift control click view
  • Select the Size inspector
  • Set the Height to a larger number
    xcode set view height

This will extend the size of the View Controller, but most likely will move the objects to occupy the whole space.

If some of the objects disappear from the visible area of the View, you can set the coordinates of the upper left corner to move them back to the visible region.

  • Open the Storyboard
  • Open the Document Outline view
  • Select the object you want to move
    xcode select object in outline view
  • Open the Utilities view
  • Select the Size inspector
  • Set the Y coordinate to a number that is within the visible area
    xcode set object position
  • Now you can click the object the move it with the mouse

Apple Objective-C programming fundamentals. Working with Data, Part 2, Create the data model

In this part of the series we will continue the development of our data store app that we set up in the first part of the series.

Create the Data Model

  • Open your sample application that you created in the first part
  • Open the Project Navigator
  • Select the Supporting Files group
  • Click the plus (+) sign in the lower left corner of the screen
  • Select New File… in the pop-up
  • Under iOS select Core Data on the left side
  • Select the Data Model icon in the middle of the window
  •  Click the Next to save the file

xcode create data model

 

Add an Entity to the data model

  • Open the .xdatamodeld file in the Project Navigator
  • Click the Add Entity button at the bottom of the screen
    xcode data add entity
  • In the upper right corner of the window under Entities name the entity Event
    xcode data entity name

Add an attribute to the Entity

  • Click the plus (+) sign at the bottom of the Attribute section of the window
    xcode data add attribute
  • Name the attribute creationDate, and set the type to Date in the pop-up menu
    xcode data attribute date
  • Add another attribute, name it as latitude and set the type to Double
  • Add a third attribute, name it longitude and set the type to Double
    As you are adding the new attributes the rows jump around to be displayed alphabetically, so make sure you are setting the type of the correct row.
    The attributes of the Event entity should look like this
    xcode data event attributes

Create a custom class to represent the Event entity to be able to create methods for the entity

  • Select the Event entity on the window
  • In the File menu select New -> New File…
  • In the New File dialog, select NSManagedObject subclass
    xcode data create managed object subclass
  • Click the Next button
  • Save the file in the project folder

Import the new class into the ViewController

  • Add the following to the RootViewController.m implementation file
    #import "Event.h"

Apple Objective-C programming fundamentals. Working with Data, Part 1, The App

This article will guide you to create an app that stores data on the user’s device. To create our sample app to store data on the user’s device

  • Start Xcode, the Apple IDE for IOS development
  • Create a new project
  • Open the AppDelegate.h file and enter the following into the @interface section before the @end
    @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
    @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    
    - (NSURL *)applicationDocumentsDirectory;
    - (void)saveContext;

    The lines above define three properties and two methods. The properties provide access to the Core Data framework of IOS, and the saveContext method will save you changes in the data file.

The Apple Core Data framework uses the following terminology

managed object

The table row

managed object context

Table rows that are in the memory and not saved to the database yet

managed object model

Describes the database, stores the relationships between the tables

entity description

Describes a table

persistent store coordinator

Manages a collection of persistent object stores, data files on the disk

 

  • In Xcode create a new class: RootViewController and make it the subclass of UITableViewController

xcode rootviewcontroller

  • Open the RootViewController.h header file and replace the content with the following
#import <CoreLocation/CoreLocation.h>

@interface RootViewController : UITableViewController  {

    NSMutableArray *eventsArray;
    NSManagedObjectContext *managedObjectContext;

    CLLocationManager *locationManager;
    UIBarButtonItem *addButton;
}

@property (nonatomic, retain) NSMutableArray *eventsArray;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) UIBarButtonItem *addButton;

@end
  • Open the RootViewController.m class file and add the following to the @implementation section
// Synthesize the properties to tell the compiler how to name them
@synthesize eventsArray;
@synthesize managedObjectContext;
@synthesize addButton;
@synthesize locationManager;
  • Write the Accessor Method for the Core Location Manager
// Create an accessor method to dynamically create the Core Location manager on demand
- (CLLocationManager *)locationManager {

    if (locationManager != nil) {
        return locationManager;
    }

    locationManager = [[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    locationManager.delegate = self;

    return locationManager;
}
  • Add the following two Core Location manager delegate methods
// Implement two delegate methods to enable and disable the Add button as appropriate.
// If the Core Location manager is generating updates, then enable the button;
// if the Core Location manager is failing, then disable the button
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    addButton.enabled = YES;
}

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error {
    addButton.enabled = NO;
}
  • Replace the implementation of viewDidLoad with the following:
- (void)viewDidLoad {

    [super viewDidLoad];

    // Set the title.
    self.title = @"Locations";

    // Set up the buttons.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    // The viewDidLoad method needs to set up the Core Location manager and the Add and Edit buttons.
    addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
    target:self action:@selector(addEvent)];
    addButton.enabled = NO;
    self.navigationItem.rightBarButtonItem = addButton;

    // Start the location manager.
    [[self locationManager] startUpdatingLocation];
}
  • Implement Methods for Memory Management
// Replace the existing implementations of viewDidUnload and dealloc. The implementation of viewDidUnload // should relinquish ownership of anything created in viewDidLoad that can be recreated.
- (void)viewDidUnload {
    self.eventsArray = nil;
    self.locationManager = nil;
    self.addButton = nil;
}

Add the Navigation Bar to the top of the view

  • Open the Story Board in the Project Navigator
  • Select the FirstView
  • Drag a Navigation Bar to the top of the view from the Object library
  • Drag a Bar Button Item to the left side of the Navigation Bar and set the Identifier to Edit
  • Drag a Bar Button Item to the right side of the Navigation Bar and set the Identifier to Add

Configuring the Application Delegate

The application delegate is responsible for creating and configuring the root view controller and a navigation controller to contain it.

Add the Navigation Controller Property

    • In the application delegate’s header file (AppDelegate.h), before the @interface section add an instance variable:
      UINavigationController *navigationController;
    • Add the property declaration:
      @property (nonatomic, retain) UINavigationController *navigationController;

 

Implement the Application Delegate

In the application delegate’s implementation file (AppDelegate.m):

  • Before the @implementation block of the application delegate class, import the RootViewController class’s header file:
    #import "RootViewController.h"
  • In the @implementation block of the application delegate class, synthesize the navigation controller property:
    @synthesize navigationController;

     

  • Replace your application delegate’s application:didFinishLaunchingWithOptions: method with the following implementation:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        RootViewController *rootViewController = [[RootViewController alloc]
        initWithStyle:UITableViewStylePlain];
    
        NSManagedObjectContext *context = [self managedObjectContext];
        if (!context) {
            // Handle the error.
        }
        // Pass the managed object context to the view controller.
        rootViewController.managedObjectContext = context;
    
        UINavigationController *aNavigationController = [[UINavigationController alloc]
        initWithRootViewController:rootViewController];
        self.navigationController = aNavigationController;
    
        [window addSubview:[navigationController view]];
        [window makeKeyAndVisible];
    
        return YES;
    }

Apple Objective-C programming fundamentals. Working with Dates

When you need to display date and time on your app’s screen you need an easy way to convert NSDate objects to NSString objects. Objective-C  contains methods to do the conversion, but the syntax is not simple. It is much easier to create a method that does the conversion and call that in a central place.

Create a method to convert NSDate objects to NSString using the current date format of the device.

Add a new class to the project

  • Click the + sign in the lower left corner of the Project Navigator
  • Select New File… in the pop-up menu
  • Select IOS -> Cocoa Touch -> Objective-C class
  • Click the Next button
  • Enter CommonMenthods into the Class field
  • Select NSObject in the Subclass of list
  • Click the Next button
  • Click the Create button to save the file in the project folder

Add three method signatures to the CommonMethods class

  • Open the CommonMethods.h file
  • Insert the following code into the @interface section
    + (NSString *)getDateShortString:(NSDate *)date;
    + (NSString *)getTimeShortString:(NSDate *)date;
    + (NSString *)getDateAndTimeShortString:(NSDate *)date;
    
    

Add the three methods to the implementation file

  • Open the CommonMethods.m file
  • Insert the following code into the@implementation section of the file
    // Returns the short date as a string
    + (NSString *)getDateShortString:(NSDate *)date {
        
        NSString *stringFromDate = [NSDateFormatter localizedStringFromDate:date
                                                                  dateStyle:NSDateFormatterShortStyle
                                                                  timeStyle:NSDateFormatterNoStyle];
        
        return stringFromDate;
    }
    
    // Returns the short time as a string
    + (NSString *)getTimeShortString:(NSDate *)date {
        
        NSString *stringFromDate = [NSDateFormatter localizedStringFromDate:date
                                                                  dateStyle:NSDateFormatterNoStyle
                                                                  timeStyle:NSDateFormatterShortStyle];
        
        return stringFromDate;
    }
    
    
    // Returns the short date and time as a string
    + (NSString *)getDateAndTimeShortString:(NSDate *)date {
        
        NSString *stringFromDate = [NSDateFormatter localizedStringFromDate:date
                                                                  dateStyle:NSDateFormatterShortStyle
                                                                  timeStyle:NSDateFormatterShortStyle];
        
        return stringFromDate;
    }
    

To use the new methods

Make the methods available in the class

  • Import the CommonMethods.h file into the class where you want to use the method
  • Insert the following line under the existing #import statement
    #import "lpCommonMethods.h"

Call the methods

  • Use the following syntax to display the date and time in short format set by the user
    self.startDateLabel.text = [CommonMethods getDateAndTimeShortString:self.startDate];

    where
    startDateLabel is a label on the view
    startDate is the NSDate object

Apple Objective-C programming fundamentals. Creating Segues in the Storyboard

Segue types

Segues are connections between views, so one view can call the other when the user pushes a button, or any specific object.

The Modal Segue

When the two views do not need to share information, like a login screen

The Push Segue

The push segue can pass data between the views and handle memory. This type of segue is needed for the navigation controller and tab bar controller.

 

Creating a Modal Segue

Add a button to the first view that will open the second view

  • In Xcode open the Storyboard of your application
  • Open the Utilities View in the upper right corner of the screen and select the Object libraryxcode object library
  • Drag a Text Field to the first view
  • Drag a Round Rect Button to the first view and enter Open Second Page as the title
    xcode first page

Add a new view to the Storyboard

  • From the Object library drag a View Controller to the storyboard
  • Drag a Text Field from the Object library to the second view
  • Drag a Round Rect Button from the Object library to the second view and enter Back to First Page to the title
    xcode second page

Create the segue between the views

  • Press the Control button on the keyboard and drag from the button on first view to the new view controller and release the control key and the mouse button
    xcode create segue
  • In the popup select modal
    xcode modal segue

 

Add the Text field to the interface of the first view

  • Open the ViewController.h of the new view in the Assistant Editor
  • Press the Control button and drag from the text field to the @interface section of the ViewController.h file
  • In the popup type firstTextField to the Name field and click the Connect button
    xcode first text field interface

Add the button to the interface of the first view

  • Press the Control key on the keyboard and drag the button from the first view to the @interface section of the ViewController.h file. Set the 
    • Connection to Action
    • Name to showSecondView: (including the colon)
    • Click the Connect button
      xcode first button interface

Create a a UIViewController class for the new View Controller

  • In the lower left corner of the project navigator click the plus sign (+)
  • Select New File... from the popup menu
  • On the popup window select Objective-C Class under IOS Cocoa Touch
  • Click the Next button
  • Set the name of the class to SecondViewController
  • Set the “Subclass of” to UIViewController
  • Click the Create button to place the new class into the project folder

Connect the new class to the View

  • Open the Storyboard and select the new view
  • In the Identity Inspector elect SecondViewController in the Class list

 

Add the Text field to the interface of the second view

  • Open the SecondViewController.h of the new view in the Assistant Editor
  • Press the Control button and drag from the text field to the @interface section of the SecondViewController.h file
  • In the popup type secondTextField to the Name field and click the Connect button
    xcode second text field interface

Add the button to the interface of the second view

  • Press the Control key on the keyboard and drag the button from the second view to the @interface section of the SecondViewController.h file. Set the
    • Connection to Action
    • Name to returnToFirstView: (including the colon)
    • Click the Connect button
      xcode second button interface

Apple Objective-C programming fundamentals – Part 1 – The language.

To write an application for an Apple device (iPhone, iPod, iPadn, Macintosh) Apple recommends the Ojbective-C language. Xcode, the Apple development environment (IDE) supports the usage of Objective-C. This article summarizes the basics of Objective-C for beginners of that language. It is helpful if you already have some programming experience, otherwise some terms will require additional research or learning.

The following is based on the Apple document:

http://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOS/chapters/WriteObjective-CCode/WriteObjective-CCode/WriteObjective-CCode.html

File extensions

.h Header files. Header files contain class, type, function, and constant declarations.
.m Implementation files. A file with this extension can contain both Objective-C and C code. It is sometimes called a source file.
.mm Implementation files. An implementation file with this extension can contain C++ code in addition to Objective-C and C code. Use this extension only if you actually refer to C++ classes or features from your Objective-C code.

To import all the header files of a framework

To import all the header files of a framework import the umbrella header file of the framework. The umbrella header file has the same name as the framework:

#import <MySDK/MySDK.h>

Class definition

Declare the class in the .h file

// Declare the class
@interface MyClass : NSObject
{
// Member variables, visible only within the class
    int       count;
    id        data;
    NSString* name;
}
// Public method declarations visible from outside of the class

// Instance method type (-)
- (id)initWithString: (NSString*) aName;

// Class method type (+)
+ (MyClass*)createMyClassWithString (NSString*) aName;
@end

Place the class implementation in the .m file

// Import the .h header file that declares the public interface
@import "MyClass.h"
// Implement the the class
@implementation MyClass

// Instance method (-). You have to create an instance of the class to execute this method.
- (id)initWithString: (NSString*) aName;
{
    // The code of the method
}

// Class method (+). You don't have to create an instance of the class to execute this method.  
+ (MyClass*)createMyClassWithString (NSString*) aName;
{
    // The code of the method
}
@end

Variables

MyClass *myObject1; // Static variable (the data type is specified)
id myObject2; // Dynamic type variable (it can hold any data type)
NSString *myObject3; // Static type string

Put an asterisk (*) in front of the name of the statically typed variables to indicate that those are pointers. The id type implies a pointer, so no asterisk is needed.

Methods and messaging

When you create an application, one of the most important rules is: never type the same code twice. Of course you can use copy and paste, but that is not the point. If you have to type the same line or lines multiple times, it usually makes sense to place the repeated lines in a method at one place, and just call that method from wherever it is necessary. Using this technique if you have to change the lines for any reason in the future you only have to change it at one place and the effect will be visible everywhere it is called from.

method_declaration

This method’s actual name is insertObject:atIndex: , the concatenation of all signature keywords, and the colon (:) indicates the existence of the parameters. If the method has no parameters, you can omit the colon(:)

Calling a method

In this example we will send the anObject and 0 to the insertObject:atIndex: method of the myArray object

[myArray insertObject:anObject atIndex:0];

The brackets ( [ and ] ) enclose the message expression.

You can nest message expressions to provide objects and arguments to the message expression. In the next example the mArray object and the anObject will be returned by nested message expressions:

[[myAppObject theArray] insertObject:[myAppObject objectToInsert] atIndex:0];

You can use dot notation to invoke accessor methods. The prior example would look like this with dot notation to access theArray and objectToInsert of myAppObject.

[myAppObject.theArray insertObject:myAppObject.objectToInsert atIndex:0];

You can use dot notation for assignment:

myAppObject.theArray = aNewArray;

You can use the dot notation for static type objects only. You cannot use the dot notation to reference dynamically typed objects (id type).

Class methods

Class methods are defined with the plus (+) sign, and can be called without creating an instance of the class.

The following example illustrates how you use a class method as a factory method for a class. In this case, the array method is a class method on the NSArray class—and inherited by NSMutableArray—that allocates and initializes a new instance of the class and returns it to your code.

NSMutableArray *myArray = nil;  // nil is essentially the same as NULL
// Create a new array and assign it to the myArray variable.
myArray = [NSMutableArray array];

Properties and Accessor Methods

Accessor methods set and get the values of properties

Declare public properties in the @interface section of the header file, private properties in the .m source file.

Define the userName string property:

@property (nonatomic, copy) NSString *c;

The compiler automatically creates ( synthesizes ) the _userName private instance variable to store the value of the property.

It also generates two accessor methods to set and get the value of the property.

The getter method’s name mathches the  name of the property: userName

The setter method’s name is setUserName (where the first letter of the property name is capitalized)

There are options the you can use during property declaration

@property (copy) MyModelObject *theObject;  // Copy the object during assignment.
@property (readonly) NSView *rootView;      // Declare only a getter method.
@property (weak) id delegate;               // Declare delegate as a weak reference

To specify the name of the instance variable:

@synthesize enabled = _isEnabled;

To specify the name of the getter accessor method:

@property (assign, getter=isEnabled) BOOL enabled; // Assign new value, change name of getter method

Blocks

Use blocks to be able to call methods a simpler way. Blocks hide the complexity of method calls, and provide simple interfaces over complex lines of code.

blocks

You can call this block with the following code:

int result = myBlock(4); // result is 28

The block has read only access to methods, properties, global, and instance variables in the context it is defined. To grant write access to variables declare them with the __block modifier.

Protocols and Categories

In Objective-C a class can inherit from one parent class only, but using protocols and categories you can implement methods in your class defined in multiple places without inheriting from multiple classes.

Protocols

When you add a protocol to the definition of a class the new class will be able to implement the methods of the protocol. This way multiple classes can implement the same protocol and a class can implement multiple protocols without inheriting from multiple classes.

For example to “teach” the  HelloWorldViewController to behave like the UITextFieldDelegate protocol, include the name of the protocol in angle brackets ( < … > ) when you declare the class.

@interface HelloWorldViewController : UIViewController <UITextFieldDelegate> {

Protocol declarations look similar to class declarations, but protocols do not have a parent class and they do not define instance variables, but can have properties and methods. Protocols can define both required and optional methods. The following lines define a protocol with one instance method:

@protocol MyProtocol
 - (void)myProtocolMethod;
 @end

Categories

By referencing categories in the class definition you can also implement functionality in your class without inheriting from other classes. A category provides the way to group related method declarations within the header file.

The following line references a category in the class declaration on parentheses ().

@interface NSDate (NSDateCreation)

Class extension

A class extension is a place to declare private methods and properties in the implementation (.m) file. The class extension uses a special anonymous category (nothing between the parentheses).

@interface MyAppDelegate ()
    @property (strong) MyDataObject *data;
@end

Reserved terms

self Refers to the current object. Equivalent to this in C++
super Refers to the super class (the ancestor of the current class)
To invoke a method implemented by the current class
[self doSomeWork];

To invoke a property accessor in the current class

NSString *theName = self.name;

Defined types

Type Description and literal
id The dynamic object type. The negative literal for both dynamically and statically typed objects is nil.
Class The dynamic class type. Its negative literal is Nil.
SEL The data type (typedef) of a selector; this data type represents a method signature at runtime. Its negative literal is NULL.
BOOL A Boolean type. The literal values are YES and NO.

Checking for null values

NSDate *dateOfHire = [employee dateOfHire];
if (dateOfHire != nil) {
    // The dateOfHire is not null
// handle this case }

or

NSDate *dateOfHire = [employee dateOfHire];
if (dateOfHire) {
    // The dateOfHire is not null
    // handle this case
}

or if you do not need a reference to the object

if ([employee dateOfHire]) {
    // handle this case
}

Testing boolean values

BOOL equal = [objectA isEqual:objectB];
if (equal == YES) {
    // handle this case
}