This Blog is for all iOS App Developers to get the code samples and working Code directly from the Blog.Iam requesting to all please add your inputs as well for the Blog can useful to all.
Search This Blog
Monday, November 22, 2010
Adding Right Bar Button Item
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
[rightBarButtonItem release];
Tuesday, October 26, 2010
SQLite
Hi All,
I have been creating an App using TableView with SQLite Manager….As a Beginner Like many others I too visited many sites in search of understanding about tableviews and how to Integrate it with Database….Here I am giving you all a detailed explanation of about TableViews and Database….let us look at it….
AIM OF THE Project: Here our Aim is Afterwhen launching into the Application you get list of Animals names Displayed and when you click on those animal names you get details of those animals in the next view.
So Initially for developing any project you must have:
* Database —- At first we must have our database ready in our Hand in order to make our lifes easy for using that in our Application.
Now let us look at how to create Database using SQLite Manager….
Foreign key (Missing):
SQlite Manager: Is easy to use and create database but the only issue with it is THERE IS NO FOREIGN KEY OPTION….Foreign keys Constraint is Missing in SQLite Manager.
SQLite3: In the NEW VERSION of SQLite 3.6.19 and latest versions they have added the Foreign key concepts in them. But remember SQLITE3 is Different from SQLite Manager.
Download SQLite Manager Add-on from FireFox and then Open Firefox > Tools(Menu) > SQLite Manager
Opening SQLite Manager from Firefox
Then Menu (In SQLite Manager)> (click) NewDatabase > SampleDB( Name of Database )
Then select the database from the Directory (option on the top, Go to your Folder) > SampleDB(select your Database)
After that From the Menu on the Top in SQLite Manager you will find Different options for Creating Table, Editing Table etc….so from that Click Create Table and then create tables after that Insert Data into those using “Insert Into” Statement into those tables….
Inserting data into those tables We Must go to EXECUTE SQL (Option in SQLite Manager ) > Write Queary for Inserting data into the table > RunSQL
In this App for SampleDB, I wrote two Tables called:
1) Animals 2) Descsription —- here is how the database look like….
Screen shot 2010-04-07 at 12.13.23 AMSo We have completed Creating the DataBase for our Project,now we will be jumping into X-Code for Developing the App….
TableViews:
In Table Views the most important thing we need to keep track is switching between the Views….In my Project I have two views
1) For the First View I am inserting the data Manually
2) For the Second View I am Inserting data into tableview from the DataBase.
* so Initially Go to X-Code > iPhoneOS > Navigational-based Applications > SampleTableViewApp (Name of The App) > Choose
Screen shot 2010-04-07 at 3.06.08 AMNow you see the Couple of Files Generated for us….
Here you see 1) RootViewController.h 2) RootViewController.m 3) SampleTableViewAppDeligate.h 4) SampleTableViewAppDeligate.m 5) RootViewController.xib
These are the Files generated by X-Code and you can see those files in Classes Folder and Resources Folder.
Adding SQLite3 lib file: Before starting the code we have to Add the SQLite3 Library into the Framework in the Application.
(right Click) Frameworks > Add File > Add Existing Frameworks > LibSqlite3.0.dylib > Add
FMDB Wrapper: I am using FMDB Wrapper as an alternative for SQLite3 as it has easy way of steps for accessing the DataBase. You can download this wrapper from Google. After downloading JUST DRAG THE FMDB FOLDER INTO YOUR APPLICATION.
Adding Database: Next Step is Add Database file to your Application
Go to your DataBase folder where you stored your SampleDB > Drag it in to your App ( You can store it in anywhere )
Coding: Let US Start coding the App…..so
The Next Step is We have Got the Files above and now Go to:
(right click on) SampleTableViewApp > Add > NewFile > UIViewController SubClass > Next > ElephantViewController.m (Name of File) > Click Checkbox to add .h Files as shown in Figure.
Screen shot 2010-04-07 at 2.24.32 PMIn The Same way Add the LionViewController file….
Screen shot 2010-04-07 at 2.24.55 PM
Don’t get confused with the RootViewController,Deligate file, ElephantViewControllerfiles, LionViewController…. I will Explain you all those….
RootViewController: It is the First View of our App
ElephantViewController, LionViewController: These are the Detailed View of the items which are displayed in the first view
Deligete Files: This is the File which have all the details of deligate methods of TableView.
So now we have our RootView files and the DetailedView file of the Root View….Now we will code our RootViewController File:
Steps:
1) RootViewController.h : Import “AnimalViewController” , then Create An Mutable Array for storing the Elements. Here is the code below:
#import <UIKit/UILit.h>
#import "ElephantViewController.h"
#import "LionViewController.h"
@interface RootViewController : UITableViewController
{
NSMutableArray *mAnimal;
}
@end
2) Go to RootViewController.m: then add the below code in View Did Load Function:
Here we are adding objects in the Array and Setting Title to the First View of The App….Every thing is explained in the Code:
- (void)viewDidLoad
{
[super viewDidLoad];
/* Here we have allocated some memory to the Array object so we have to release it in Dealloc Function */
mAnimal = [[NSMutableArray alloc] init];
/* Next Step is Adding Objects to the Array*/
[mAnimal addObject:@"Elephant"];
[mAnimal addObject:@"Lion"];
/* Setting Title to the First View */
[self setTitle:@"Quote Category"];
}
Modifying TableView Deligate Methods:
3) In this step we have to Modify the Deligate Methods of the Tableview according to our App Requirements:
These can be found in the Bottom after the ” #pragma mark Table view methods” Line. so Add the Below Code in those Methods:
Here the First Method we have to change is “NumberOfRowsInSection” by default it is “0″ but We want our Rows to be Displayed as the number of elements in the Array so Update your Code as shown below:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [mAnimal count];
}
4) In this step we can Configure the cells in the TableView by changing this Method “cellForRowAtIndexPath”
we can set the Accessory type like” > ” as shown in the iPhone or iPod:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/* These are the Default Methods we don't need to configure them */
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
/* Configure the cell.
We have to start configuring cells from here
*/
[cell setText:[[qCategoriesList objectAtIndex:indexPath.row] retain]];
/* set the Accessory Type to our Cells like ">"*/
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return cell;
}
5) Next Most Important step is “Pushing the First View to Second View” for this uncomment the “DidSelectRow” and do the following code:
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/* all the Methods are already given in this Function, We just need to change them according to our Requirements
If we Select Elephant then the View has to Push into another View giving details abuot the Elephant */
// Elephant View
if([[mAnimal objectAtIndex:indexPath.row] isEqual:@"Elephat"])
{
ElephantViewController *mEle = [[ElephantViewController alloc] initWithNibName:@"ElephantViewController" bundle:nil];
//Setting title to the TableView
[mEle setTitle:@"Elephant Details"];
//Pushing the View from RootView to ElephantView
[self.navigationController pushViewController:mEle animated:YES];
//releasing the Allocated Object
[mEle release];
}
// Lion View
if([[mAnimal objectAtIndex:indexPath.row] isEqual:@"Lion"])
{
LionViewController *mLion = [[LionViewController alloc] initWithNibName:@"LionViewController" bundle:nil];
//Setting title to the TableView
[mLion setTitle:@"Lion Details"];
//Pushing the View from RootView to ElephantView
[self.navigationController pushViewController:mLion animated:YES];
//releasing the Allocated Object
[mLion release];
}
/* There ends the Pushing of our view now we have to code in our detailed views of Elephant and Lion in order to display data about them----we are displaying this data from the Database */
// Navigation logic may go here -- for example, create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController animated:YES];
// [anotherViewController release];
}
Now we have to Code Our Detailed Views and Display data in them…We first Code our ElephantViewController
6) Now As we have created our “ElephatViewController” as a SubClass of UIViewController we need to Change that to UITableViewController Class
i:e “ElephantTableViewController” as we want to display data in a TableView in ElephantViewController. Here is the Code of that:
/* We have to import the FMDB Headers in our file as we have to use its queary methods for accessing the DB*/
#import
#import "FMDatabase.h"
#import "FMResultSet.h"
/*
It is Like this
@interface ElephantViewController : UIViewController
Now we are going to change it like this:
*/
@interface ElephantViewController : UITableViewController
{
// We have to Create an Array in order to Hold the Data coming from the DataBase
NSMutableArray *aElephant;
//NSString object is used to hold the elements retrived from the database
NSString *eleData;
}
@property (nonatomic,retain) NSString* eleData;
@end
7) Now as we did the .H file we have to implement the database connection and get the results form the DB
here how it goes: now go to ElephantViewController.m File then do this code….
#import "ElephantViewController.h"
@implementation ElephantViewController
@synthesize eleData;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
/* Now here we have to write the code from the database to display the details */
aElephant = [[NSMutableArray alloc] init];
/*
Here we have to set the path
We are creating the path for the datbase file in order to access
*/
NSString *path = [[NSBundle mainBundle] pathForResource:@"SampleDB" ofType:@"sqlite"];
/* FMDatabase here is used to take the database path */
FMDatabase *db = [[FMDatabase alloc] initWithPath:path];
/* Here we are opening the datase in order to access it */
[db open];
/*
Then the next step here is taking the datbase result using the sqlqueary and then carrying that result into the resultset object
Resultset for Elephant: select * from Description where a_id=1; here description is the table, a_id is the id of Elephant it is
the primary key in animals table
*/
FMResultSet *fResult= [db executeQuery:@"SELECT * FROM description WHERE a_id=1"];
/* Now we have to take these results in to a loop and then repeteadly loop it in order to get all the data in a our Array Object */
while([fResult next])
{
/* taking results from database to a string "eleData" */
eleData = [fResult stringForColumn:@"desc"];
/* adding data from the string object to Array */
[aElephant addObject:eleData];
/* Checking weather data has come or not */
NSLog(@"The data is %@=",eleData);
}
/* Closing the Database */
[db close];
}
And now we got our data form the Database and stored it in the array Element
8) In this Step as we got our data we have to now display that data in the table view of ElephantViewController.
For that we need deligate methods of TableView….Just Go to UITableView and copy the methods from there under the” #pragma mark Table view methods”….
So now we only copy the required methods of Deligate….methods with code are shown below, we don’t need to copy the “DidSelectRow”
as we are not pushing this view to another view…we are just displaying the data here…. copy deligate methods above the dealloc():
/* UITABLEVIEW Deligate Methods */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [aElephant count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
//We are configuring my cells in table view
NSString *eData = [aElephant objectAtIndex:indexPath.row];
cell.textLabel.text = eData;
return cell;
}
So Finally we did the Code part now we have to do the Interface builder for the ElephantViewController….
Remember in the above RootViewController we did not do any interface builder why because by default the TableView is added to it….as initially we selected
“Navigation based Application”….
For adding the TableView in the ElephantViewController (click)ElephantViewController.xib > then drop TableView on to the View Window.
Important Info:
In the Connection we have to connect the datasource and deligate to the FilesOwner in the Interface Builder.
9) We have completed the Detailed View of ElephantViewController now we have to do the LionViewController:
Repeat the same code for LionView Controller after doing that Save the files and Interface Builder….
X-Code > Build > Go
This is the Final Result of our Application:
RootViewController RootViewController View
ElephantViewController(Detailed View) Detailed View of ElephantViewController
Detailed LionViewController Detailed View of LionViewController
And So Thus our Project gets Succeeded….Hope this article helps you….
Enumerators
Objective-C Enumerators allow variables to be declared with a predefined list of valid values, each of which is assigned a name that can be used when setting the variable. This has the advantage of making the code easier to read and understand.
Why Use Enumerators
As previously described, enumerators allow the programmer to predefine the range of values that can be assigned to a variable and use self-explanatory names when setting those values. The benefits of this are twofold. Firstly this makes code easier to read and understand and secondly this, to a certain extent, allows control of the values that can be assigned (though as we will see later in this chapter, enforcement is rather weak).
Declaring an Enumeration
The syntax for declaring an enumeration is as follows:
enum
In the above syntax outline, enum is the keyword that tells the compiler we are creating an enumeration,
enum
For example, we can specify an enumeration for the days of the week:
enum daysofweek {monday, tuesday, wednesday, thursday, friday, saturday, sunday};
In the above construct, monday is equal to 0, tuesday is 1 and so on. If we specify a number for just one entry, the remaining values will follow on from that number. For example:
enum daysofweek {monday = 1, tuesday, wednesday, thursday, friday, saturday, sunday};
In this case, monday will be 1, tuesday will be 2 etc.
Alternatively we can specify a value for each entry in the enumeration:
enum temperature {cold = 5, warm = 50, hot = 95};
Creating and Using an Enumeration
Having declared an enumeration the next step is to declare a variable of that type. For example, to create a variable called currentTemp from our temperature enumerator type we would write the following code:
enum temperature currentTemp;
Now that we have created a variable based on our enumerator data type, we can try setting a value using one of the value names and then displaying the current value of the variable:
currentTemp = hot;
NSLog (@"Current temperature is %i", currentTemp);
When compiled and executed, the above code will output the following:
2009-10-21 10:25:46.640 t[11525:10b] Current temperature is 95
As we can see, although we assigned hot to our currentTemp variable, Objective-C translated it to the corresponding number 95. If we attempt to assign a value using an undefined name as follows the code will fail to compile with a 'tepid' undeclared error message:
currentTemp = tepid;
We can, however, bypass this system by assigning a number directly to the variable:
currentTemp = 109;
The above code will, unfortunately, compile and run.
Enumerators and Variable Names
When using enumerators in Objective-C it is important to be aware that both the enumerator name and the value names are treated as symbols that must be unique within the given scope. For example, because we use the value name hot in our temperature enumerator we cannot then use hot as a variable name within the same scope (for information on variable scope refer to Objective-C Variable Scope and Storage Class). Take, for the example, the following code. Here we have our temperature enumerator and also a declaration for a variable named hot:
enum temperature {cold = 5, warm = 50, hot = 95};
enum temperature currentTemp;
int hot = 100;
currentTemp = hot;
NSLog (@"Current temperature is %i", currentTemp);
If we attempt to compile this code, an error will result informing us that a duplicate symbol has been detected:
temp.m: In function 'main':
temp.m:14: error: 'hot' redeclared as different kind of symbol
temp.m:10: error: previous definition of 'hot' was here
NSFileManager Class
Contents
• 1 Creating an NSFileManager Instance
• 2 Checking if a File Exists
• 3 Comparing the Contents of Two Files
• 4 Checking if a File is Readable/Writable/Executable/Deletable
• 5 Moving/Renaming a File
• 6 Copying a File
• 7 Removing a File
• 8 Creating a Symbolic Link
• 9 Reading and Writing Files with NSFileManager
• 10 Working with Files using the NSFileHandle Class
• 11 Creating an NSFileHandle Object
• 12 NSFileHandle File Offsets and Seeking
• 13 Reading Data from a File
• 14 Writing Data to a File
• 15 Truncating a File
Creating an NSFileManager Instance
First we need to recap the steps necessary to create an instance of the NSFileManager class. As discussed in the previous chapter, the NSFileManager class contains a class method named defaultManager that is used to create an instance of the class. For example:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
Checking if a File Exists
The NSFileManager class contains an instance method named fileExistsAtPath that checks whether a specified file already exists. The method takes as an argument an NSString object containing the path to file and returns a boolean YES or NO value indicating the presence or otherwise of that file:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: @"/tmp/myfile.txt" ] == YES)
NSLog (@"File exists");
else
NSLog (@"File not found");
Comparing the Contents of Two Files
The contents of two files can be compared for equality using the contentsEqualAtPath method. This method takes as arguments the paths to the two files to be compared and returns a boolean YES or NO to indicate whether the file contents match:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr contentsEqualAtPath: @"/tmp/myfile.txt" andPath: @"/tmp/sales.txt"] == YES)
NSLog (@"File contents match");
else
NSLog (@"File contents do not match");
Checking if a File is Readable/Writable/Executable/Deletable
Most operating systems provide some level of file access control. These typically take the form of attributes that control the level of access to a file for each user or user group. As such, it is not a certainty that your program will have read or write access to a particular file, or the appropriate permissions to delete or execute it. The quickest way to find out if your program has a particular access permission is to use the isReadableFileAtPath, isWritableFileAtPath, isExecutableFileAtPath and isDeletableFileAtPath methods. Each method takes a single argument in the form of the path to the file to be checked and returns a boolean YES or NO result. For example, the following code excerpt checks to find out if a file is writable:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr isWritableFileAtPath: @"/tmp/myfile.txt"] == YES)
NSLog (@"File is writable");
else
NSLog (@"File is read only");
To check for other access permissions simply substitute the corresponding method name in place of isWritableFileAtPath in the above example.
Moving/Renaming a File
A file may be renamed (assuming adequate permissions) using the moveItemAtPath method. This method returns a boolean YES or NO result and takes as arguments the pathname for the file to be moved, the destination path and an optional NSError object into which information describing any errors encountered during the operation will be placed. If no error description information is required, this argument may be set to NULL. Note that if the destination file path already exists this operation will fail.
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr moveItemAtPath: @"/tmp/myfile.txt" toPath: @"/tmp/newfile.txt" error: NULL] == YES)
NSLog (@"Move successful");
else
NSLog (@"Move failed");
Copying a File
File copying can be achieved using the copyItemAtPath method. As with the move method, this takes as arguments the source and destination pathnames and an optional NSError object. Success of the operation is indicated by the returned boolean value:
if ([filemgr copyItemAtPath: @"/tmp/myfile.txt" toPath: @"/Users/demo/newfile.txt" error: NULL] == YES)
NSLog (@"Copy successful");
else
NSLog (@"Copy failed");
Removing a File
The removeItemAtPath method removes the specified file from the file system. The method takes as arguments the pathname of the file to be removed and an optional NSError object. The success of the operation is, as usual, reported in the form of a boolean YES or NO return value:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr removeItemAtPath: @"/tmp/myfile.txt" error: NULL] == YES)
NSLog (@"Remove successful");
else
NSLog (@"Remove failed");
Creating a Symbolic Link
A symbolic link to a particular file may be created using the createSymbolicLinkAtPath method. This takes arguments the path of the symbolic link, the path to the file to which the link is to refer and an optional NSError object. For example, the following code creates a symbolic link from /Users/demo/file1.txt that links to the pre-existing file /tmp/myfile.txt:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr createSymbolicLinkAtPath: @"/Users/demo/file1.txt"
withDestinationPath: @"/tmp/myfile.txt" error: NULL] == YES)
NSLog (@"Remove successful");
else
NSLog (@"Remove failed");
Reading and Writing Files with NSFileManager
The NSFileManager class includes some basic file reading and writing capabilities. these capabilities are somewhat limited when compared to the options provided by the NSFileHandle class, but can be useful nonetheless.
Firstly, the contents of a file may be read and stored in an NSData object through the use of the contentsAtPath method:
NSFileManager *filemgr;
NSData *databuffer;
filemgr = [NSFileManager defaultManager];
databuffer = [filemgr contentsAtPath: @"/tmp/myfile.txt" ];
Having stored the contents of a file in an NSData object, that data may subsequently be written out to a new file using the createFileAtPath method:
databuffer = [filemgr contentsAtPath: @"/tmp/myfile.txt" ];
[filemgr createFileAtPath: @"/tmp/newfile.txt" contents: databuffer attributes: nil];
In the above example we have essentially copied the contents from an existing file to a new file. This, however, gives us no control over how much data is to be read or written and does not allow us to append data to the end of an existing file. If the file /tmp/newfile.txt in the above example had already existed it, and any data it contained, would have been overwritten by the contents of the source file. Clearly some more flexible mechanism is required. This is provided by the Foundation Framework in the form of the NSFileHandle class.
Working with Files using the NSFileHandle Class
The NSFileHandle class provides a range of methods designed to provide a more advanced mechanism for working with files. In addition to files, this class can also be used for working with devices and network sockets. In the following sections we will look at some of the more common uses for this class.
Creating an NSFileHandle Object
An NSFileHandle object can be created when opening a file for reading, writing or updating (reading and writing). This is achieved using the fileHandleForReadingAtPath, fileHandleForWritingAtPath and fileHandleForUpdatingAtPath methods respectively. Having opened a file, it must subsequently be closed when we have finished working with it using the closeFile method. If an attempt to open a file fails, for example because an attempt is made to open a non-existent file for reading, these methods return nil.
For example, the following code excerpt opens a file for reading and writing and then closes it without actually doing anything to the file:
NSFileHandle *file;
file = [NSFileHandle fileHandleForWritingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
NSLog(@"Failed to open file");
[file closeFile];
NSFileHandle File Offsets and Seeking
NSFileHandle objects maintain a pointer to the current position in a file. This is referred to as the offset. When a file is first opened the offset is set to 0 (the beginning of the file). This means that any read or write operations we perform using the NSFileHandle methods will take place at offset 0 in the file. To perform operations at different locations in a file (for example to append data to the end of the file) it is first necessary to seek to the required offset. For example to move the current offset to the end of the file, use the seekToEndOfFile method. Alternatively, seekToFileOffset allows you to specify the precise location in the file to which the offset is to be positioned. Finally, the current offset may be identified using the offsetInFile method. In order to accommodate large files, the offset is stored in the form of an unsigned long long.
The following example opens a file for reading and then performs a number of method calls to move the offset to different positions, outputting the current offset after each move:
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
NSLog(@"Failed to open file");
NSLog (@"Offset = %llu", [file offsetInFile]);
[file seekToEndOfFile];
NSLog (@"Offset = %llu", [file offsetInFile]);
[file seekToFileOffset: 30];
NSLog (@"Offset = %llu", [file offsetInFile]);
[file closeFile];
File offsets are a key aspect of working with files using the NSFileHandle class so it is worth taking extra time to make sure you understand the concept. Without knowing where the current offset is in a file it is impossible to know where in the file data will be read or written.
Reading Data from a File
Once a file has been opened and assigned a file handle, the contents of that file may be read from the current offset position. The readDataOfLength method reads a specified number of bytes of data from the file starting at the current offset. For example, the following code reads 5 bytes of data from offset 10 in a file. The data read is returned encapsulated in an NSData object:
NSData *databuffer;
file = [NSFileHandle fileHandleForReadingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
NSLog(@"Failed to open file");
[file seekToFileOffset: 10];
databuffer = [file readDataOfLength: 5];
[file closeFile];
Alternatively, the readDataToEndOfFile method will read all the data in the file starting at the current offset and ending at the end of the file.
Writing Data to a File
The writeData method writes the data contained in an NSData object to the file starting at the location of the offset. Note that this does not insert data but rather overwrites any existing data in the file at the corresponding location.
To see this in action we need to begin with a file. Using a text editor, create a file named quickfox.txt, enter the following text and save it in the /tmp directory:
The quick brown fox jumped over the lazy dog
Next, we will write a program that opens the file for updating, seeks to position 10 and then writes some data at that location:
#import
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSFileHandle *file;
NSMutableData *data;
const char *bytestring = "black dog";
data = [NSMutableData dataWithBytes:bytestring length:strlen(bytestring)];
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/quickfox.txt"];
if (file == nil)
NSLog(@"Failed to open file");
[file seekToFileOffset: 10];
[file writeData: data];
[file closeFile];
[pool drain];
return 0;
}
When the above program is compiled and executed the contents of the quickfox.txt will have changed to:
The quick black dog jumped over the lazy dog
Truncating a File
A file may be truncated at the specified offset using the truncateFileAtOffset method. To delete the entire contents of a file, specify an offset of 0 when calling this method:
NSFileHandle *file;
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/quickfox.txt"];
if (file == nil)
NSLog(@"Failed to open file");
[file truncateFileAtOffset: 0];
[file closeFile];
Monday, October 25, 2010
NSString Detailed Description
Contents
[hide]
• 1 Strings without NSString
• 2 Declaring Constant String Objects
• 3 Creating Mutable and Immutable String Objects
• 4 Getting the Length of a String
• 5 Copying a String
• 6 Searching for a Substring
• 7 Replacing Parts of a String
• 8 String Search and Replace
• 9 Deleting Sections of a String
• 10 Extracting a Subsection of a String
• 11 Inserting Text into a String
• 12 Appending Text to the End of a String
• 13 Comparing Strings
• 14 Checking for String Prefixes and Suffixes
• 15 Converting to Upper or Lower Case
• 16 Converting Strings to Numbers
• 17 Converting a String Object to ASCII
1) [edit] Strings without NSString
As we've already discussed, Objective-C is built upon the C programming language. C also has a mechanism for dealing with strings, but because C is not an object oriented programming language it does not have any of the advantages offered to us through the NSString class. For example, to use the C approach to creating strings we have to set up a pointer to a string of characters:
char *myString = "This is a C character string";
Alternatively, we could define a C style character array to contain a string:
Having created the string we literally have nothing but a section of memory where a null terminated string of characters is located. If we want to do anything to manipulate the string we will have to write our own code to do it.
By using NSString, however, we get access to a wide range of methods provided with that class to manipulate our string without having to write all the code ourselves. My first ever job involved writing complex programs in the C programming language, and from bitter experience I can tell you that the hardest part of that job was writing code to work with strings. My life would have been much easier if Objective-C and the NSString class had existed all those years ago.
In addition, C style character strings are composed of single byte characters and therefore limited in the range of characters that can be stored. This usually becomes a problem when dealing with non-ASCII character sets used by foreign languages. NSString objects, on the other hand, are comprised of multibyte Unicode characters and can handle just about any language character set.
[edit] Declaring Constant String Objects
A constant string object is declared by encapsulating the string in double quotes (") preceded by an @ sign. For example:
@"This is a constant character string object";
In order to display the current value of a string object using NSLog, simply reference the string using '%@' as follows:
NSLog (@"%@", @"This is a constant character string object");
Even though all we are doing here is creating a constant string object, keep in mind that this is still an object. As such, it has a range of methods that we can call on it. For example string objects have a length method that returns the number of characters in the string. We can, therefore, call this on a constant string object:
int len = [@"Hello" length];
NSLog (@"Length of string = %i", len);
The above code declares a constant string object containing the word "Hello" and calls the length method of object. The result is assigned to an integer variable named len which in turn is displayed using NSLog. When compiled and executed, we get the following output:
Length of string = 5
Constant string objects are actually instantiated from the NSConstantString class which, much like the other classes we will look at in this chapter, is actually a subclass of the NSString class. In practice, given the way that constant strings are used, it is unlikely that you will need to specifically declare your string constants as being of type NSConstantString. It is more likely that you will declare the string as we have done in this section and let the compiler handle the rest.
[edit] Creating Mutable and Immutable String Objects
Two additional types of Objective-C string objects are mutable and immutable. When you create a string object of type NSString you are creating an immutable string object. This means that once a string has been assigned to the object, that string cannot subsequently be modified in any way.
NSString *string1 = @"This string is immutable";
Mutable string objects, on the other hand, are declared using the NSMutableString class and allow the string contained within the object to be modified using a variety of methods (some of which will be covered in the remainder of this chapter). NSMutableString is a subclass of NSString, which in turn is a subclass of NSObject. Mutable strings cannot be initialized simply by assigning a constant string object as we did above since that will just give us a pointer to an immutable constant string object. Instead, the string constant must be copied into the mutable string object. For example:
NSMutableString *string2 = [NSMutableString stringWithString:@"This string is mutable"];
Once a string has been declared as immutable, the only way to get a mutable version of the string is to create a mutable string object and copy the contents of the immutable string object to it. This can be achieved using the NSMutableString stringWithString class method. For example:
NSString *string1 = @"This is a string";
NSMutableString *string2;
string2 = [NSMutableString stringWithString: string1];
Once executed, the above code will create an immutable string object (string1) initialized with the text "This is a string" and an empty pointer to an immutable string object (string2). The stringWithString class method of the NSMutableString class is then called, passing though the immutable string1 as an argument. This method returns a new object containing the immutable string and assigns it to string2. We now have a mutable copy of the immutable string1 object.
[edit] Getting the Length of a String
The length of the string in a string object can be obtained by accessing the length method of the string object:
NSString *string1 = @"This string is Immutable";
int len = [string1 length];
NSLog (@"String length is %i", len);
The above code fragment will produce the following output when executed:
String length is 24
[edit] Copying a String
When copying one string object to another it might be tempting to think that you can simply assign the object from one variable to another. For example, if we had two integer variables and wanted to assign the value of one to the other we could simply do the following:
int a = 10;
int b;
a = b;
After the above code has executed, both variables a and b will contain the value 10. The same is not, however, true of string objects. Take for example the following code fragment:
NSMutableString *string1;
NSMutableString *string2;
string1 = [NSMutableString stringWithString: @"This is a string"];
string2 = string1;
What we have achieved here is to create two variables (string1 and string2) that point to the memory location of the same string object. This is because the '*' before the variable names in the declarations indicates that this is a pointer to an object, not an actual object. Any time that we access the object referenced by either of these pointers we will, in fact, be accessing the same object. To prove this, we can make a change using the string2 reference and then display the string associated with both the string1 and string1 object pointers:
NSMutableString *string1;
NSMutableString *string2;
string1 = [NSMutableString stringWithString: @"This is a string"];
string2 = string1;
[string2 appendString: @" and it is mine!"];
NSLog (@"string1 = %@", string1);
NSLog (@"string2 = %@", string2);
The above code will display the following output, proving that both string1 and string2 point to the same object since only one reference was modified, yet both show the change:
2009-11-03 14:35:37.731 t[32239:10b] string1 = This is a string and it is mine!
2009-11-03 14:35:37.732 t[32239:10b] string2 = This is a string and it is mine!
To actually copy one string object to another string object we must use stringWithString method the NSMutableString class:
NSMutableString *string1;
NSMutableString *string2;
string1 = [NSMutableString stringWithString: @"This is a string"]; // Initialize string1
string2 = [NSMutableString stringWithString: string1]; // Copy string1 object to string2
[string2 appendString: @" and it is mine!"]; // Modify string2
NSLog (@"string1 = %@", string1);
NSLog (@"string2 = %@", string2);
When executed, the appended text appears only in the object referenced by string2 since string2 now references a different object to that referenced by string1:
2009-11-03 14:42:10.426 t[32263:10b] string1 = This is a string
2009-11-03 14:42:10.427 t[32263:10b] string2 = This is a string and it is mine!
[edit] Searching for a Substring
A common requirement when working with strings is to identify whether a particular sequence of characters appears within a string. This can be achieved using the rangeOfString method. This method returns a structure of type NSRange. The NSRange structure contains a location value providing the index into the string of the matched substring and a length value indicating the length of the match.
NSString *string1 = @"The quick brown fox jumped";
NSRange match;
match = [string1 rangeOfString: @"brown fox"];
NSLog (@"match found at index %i", match.location);
NSLog (@"match length = %i", match.length);
The NSLog call will display the location and length of the match. Note that the location is an index into the string where the match started and that the index considers the first position in a string to be 0 and not 1. As such, the location in our example will be 10 and the length will be 9.
In the event that no match is found, the rangeOfString method will set the location member of the NSRange structure to NSNotFound. For example:
NSString *string1 = @"The quick brown fox jumped";
NSRange match;
match = [string1 rangeOfString: @"brown dog"];
if (match.location == NSNotFound)
NSLog (@"Match not found");
else
NSLog (@"match found at index %i", match.location);
[edit] Replacing Parts of a String
Sections of a mutable string may be replaced by other character sequences using the replaceCharactersInRange method. This method directly modifies the string object on which the method is called so only works on mutable string objects.
This method requires two arguments. The first argument is an NSRange structure consisting of the location of the first character and the total number of characters to be replaced. The second argument is the replacement string. An NSRange structure can be created by calling NSMakeRange and passing though the location and length values as arguments. For example, to replace the word "fox" with "squirrel" in our sample mutable string object we would write the following Objective-C code:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
[string1 replaceCharactersInRange: NSMakeRange(16, 3) withString: @"squirrel"];
NSLog (@"string1 = %@", string1);
As you may have noted from the above example, the replacement string does not have to be the same length as the range being replaced. The string object and replacement method will resize the string automatically.
[edit] String Search and Replace
Previously we have covered how to perform a search in a string and how to replace a subsection of a string using the rangeOfString and replaceCharactersInRange methods respectively. The fact that both of these methods use the NSRange structure enables us to combine the two methods to perform a search and replace. In the following example, we use rangeOfString to provide us with an NSRange structure for the substring to be replace and then pass this through to replaceCharactersInRange to perform the replacement:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
[string1 replaceCharactersInRange: [string1 rangeOfString: @"brown fox"] withString: @"black dog"];
When executed, string1 will contain the string "The quick black dog jumped".
[edit] Deleting Sections of a String
Similar techniques to those described above can be used to delete a subsection of a string using the deleteCharactersInRange method. As with the preceding examples, this method accepts an NSRange structure as an argument and can be combined with the rangeOfString method to perform a search and delete:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
[string1 deleteCharactersInRange: [string1 rangeOfString: @"jumped"]];
[edit] Extracting a Subsection of a String
A subsection of a string can be extracted using the substringWithRange method. The range is specified using an NSRange structure and the extracted substring is returned in the form of an NSString object:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
NSString *string2;
string2 = [string1 substringWithRange: NSMakeRange (4, 5)];
NSLog (@"string2 = %@", string2);
When executed, the above code will output the substring assigned to string2 ("quick").
Alternatively, a substring may be extracted from a given index until the end of the string using the subStringFromIndex method. For example:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
NSString *string2;
string2 = [string1 substringFromIndex: 4];
Similarly, the subStringToIndex may be used to extract a substring from the beginning of the source string up until a specified character index into the string.
[edit] Inserting Text into a String
The insertString method inserts a substring into a string object and takes as arguments the NSString object from which the new string is to inserted and the index location into the target string where the insertion is to be performed:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
[string1 insertString: @"agile, " atIndex: 4];
[edit] Appending Text to the End of a String
Text can be appended to the end of an existing string object using the appendString method. This method directly modifies the string object on which the method is called and as such is only available for mutable string objects.
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
[string1 appendString: @" over the lazy dog"];
NSLog (@"string1 = %@", string1);
[edit] Comparing Strings
String objects cannot be compared using the equality (==) operator. The reason for this is that any attempt to perform a comparison this way will simply compare whether the two string objects are located at the same memory location. Let's take a look at this via an example:
NSString *string1 = @"My String";
NSString *string2 = @"My String";
if (string1 == string2)
NSLog (@"Strings match");
else
NSLog (@"Strings do not match");
In the above code excerpt, string1 and string2 are pointers to two different string objects both of which contain the same character strings. If we compare them using the equality operator, however, we will get a "Strings do not match" result. This is because the if (string1 == string2) test is asking whether the pointers point to the same memory location. Since string1 and string2 point to entirely different objects the answer, obviously, is no.
We can now take this a step further and change the code so that both string1 and string2 point to the same string object:
NSString *string1 = @"My String";
NSString *string2;
string2 = string1;
if (string1 == string2)
NSLog (@"Strings match");
else
NSLog (@"Strings do not match");
Now when we run the code, we get a "Strings match" result because both variables are pointing to the same object in memory.
To truly compare the actual strings contained within two string objects we must use the isEqualToString method:
NSString *string1 = @"My String";
NSString *string2 = @"My String 2";
if ([string1 isEqualToString: string2])
NSLog (@"Strings match");
else
NSLog (@"Strings do not match");
Another option is to use the compare method (to perform a case sensitive comparison) or the caseInsenstiveCompare NSString methods. These are more advanced comparison methods that can be useful when sorting strings into order.
[edit] Checking for String Prefixes and Suffixes
A string object can be tested to identify whether the string begins or ends with a particular sequence of characters (otherwise known as prefixes and suffixes). This is achieved using the hasPrefix and hasSuffix methods respectively, both of which return boolean values based on whether a match is found or not.
NSString *string1 = @"The quick brown fox jumped";
BOOL result;
result = [string1 hasPrefix: @"The"];
if (result)
NSLog (@"String begins with The");
result = [string1 hasSuffix: @"dog"];
if (result)
NSLog (@"String ends with dog");
[edit] Converting to Upper or Lower Case
The Foundation NSString classes provide a variety of methods for modifying different aspects of case within a string. Note that each of these methods returns a new string object reflecting the change, leaving the original string object unchanged.
• capitalizedString
Returns a copy of the specified string with the first letter of each word capitalized and all other characters in lower case:
NSString *string1 = @"The quicK brOwn fox jumpeD";
NSString *string2;
string2 = [string1 capitalizedString];
The above code will return a string object containing the string "The Quick Brown Fox Jumped" and assign it to the string2 variable. The string object referenced by string1 remains unmodified.
• lowercaseString
Returns a copy of the specified string with all characters in lower case:
NSString *string1 = @"The quicK brOwn fox jumpeD";
NSString *string2;
string2 = [string1 lowercaseString];
The above code will return a string object containing the string "the quick brown fox jumped" and assign it to the string2 variable. The string object referenced by string1 remains unmodified.
• uppercaseString
Returns a copy of the specified string with all characters in upper case:
NSString *string1 = @"The quicK brOwn fox jumpeD";
NSString *string2;
string2 = [string1 uppercaseString];
The above code will return a string object containing the string "THE QUICK BROWN FOX JUMPED" and assign it to the string2 variable. The string object referenced by string1 remains unmodified.
[edit] Converting Strings to Numbers
String objects can be converted to a variety of number types:
• Convert String to int
NSString *string1 = @"10";
int myInt = [string1 intValue];
NSLog (@"%i", myInt);
• Convert String to double
NSString *string1 = @"10.1092";
double myDouble = [string1 doubleValue];
NSLog (@"%f", myDouble);
• Convert String to float
NSString *string1 = @"10.1092";
float myFloat = [string1 floatValue];
NSLog (@"%f", myFloat);
• Convert String to NSInteger
NSString *string1 = @"10";
NSInteger myInteger = [string1 integerValue];
NSLog (@"%li", myInteger);
[edit] Converting a String Object to ASCII
The string contained within a string object can be extracted and converted to an ASCII C style character string using the UTF8String method. For example:
NSString *string1 = @"The quick browen fox";
const char *utfString = [string1 UTF8String];
printf ("Converted string = %s\n", utfString);
Wednesday, September 15, 2010
UIImagePickerController
- (void)takePicture:(id)sender
{
NSString *deviceType = [UIDevice currentDevice].model;
if( ![deviceType isEqualToString:@"iPhone"] )
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}
else
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}
}
UIKit FrameWork
-(void)viewDidLoad
{
CGRect webFrame = CGRectMake(0.0, 0.0, 320.0, 460.0);
UIWebView *webView = [[UIWebView alloc] initWithFrame:webFrame];
[webView setBackgroundColor:[UIColor whiteColor]];
[webView setDelegate:self];
NSString *urlAddress = @"http://www.google.com";
NSURL *url = [NSURL URLWithString:urlAddress];
*requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
[self addSubview:webView];
[webView release];
}
//Web View delegate methods
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
//started loading
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//Finished loading
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//Error in loading
}
UItextField
-(void)viewDidLoad
{
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 30, 150, 40)];
NSLog(@"LOAD");
[textField setBorderStyle:UITextBorderStyleRoundedRect];
[textField setFont:[UIFont systemFontOfSize:28]];
[textField setTextColor:[UIColor redColor]];
[textField setBackgroundColor:[UIColor yellowColor]];
[textField setAdjustsFontSizeToFitWidth:YES];
[textField setClearButtonMode:UITextFieldViewModeWhileEditing];
[textField setReturnKeyType:UIReturnKeyDone];
[textField setKeyboardAppearance:UIKeyboardAppearanceAlert];
//[textField setDelegate:self];
//[textField setText:@"SAMPLE"];
[self.view addSubview:textField];
//[textField becomeFirstResponder];
[textField release];
}
Text field Delegate Methods
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(@"BEGIN = %@", [textField text]);
}
- (void)textChanged:(NSNotification *)aNotification
{
NSLog(@"TEXT CHANGED = %@", [aNotification userInfo]);
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@"CHAR = %@", [textField text]);
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(@"RETURN = %@", [textField text]);
[textField resignFirstResponder];
return YES;
}
UISwitch
-(void)viewDidLoad
{
UISwitch *aSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(100, 290, 300, 100)];
[self.view addSubview:aSwitch];
[aSwitch release];
[aSwitch setOn:YES];
[aSwitch addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];
}
- (void)switchAction:(UISwitch *)aSwitch
{
NSLog(@"SWITCH = %d", [aSwitch isOn]);
}
UISlider
-(void)viewDidLoad
{
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(20, 320, 100, 100)];
[self.view addSubview:slider];
[slider release];
[slider setMaximumValue:100.0f];
[slider setMinimumValue:1.0f];
[slider setValue:50.0f];
[slider addTarget:self action:@selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
}
- (void)sliderAction:(id)slider
{
NSLog(@"SLIDER = %f", [(UISlider *)slider value]);
}
UIImageView
-(void)viewDidLoad
{
UIImageView *anImageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 280, 200, 200)];
//[anImageView setImage:anImage];
[anImageView setImage:[UIImage imageNamed:@"CAMPUS TOUR BLACK.png"]];
[self.view addSubview:anImageView];
[anImageView setBackgroundColor:[UIColor purpleColor]];
[anImageView setContentMode:UIViewContentModeCenter];
[anImageView release];
NSArray *imagesArray = [NSArray arrayWithObjects:[UIImage imageNamed:@"Images/bg_circle.png"], [UIImage imageNamed:@"CAMPUS TOUR BLACK.png"], nil];
[anImageView setAnimationImages:imagesArray];
[anImageView setAnimationDuration:0.5f];
[anImageView setAnimationRepeatCount:1];
[anImageView startAnimating];
//[anImageView stopAnimating];
//[anImageView isAnimating];
}
UIActivityIndicatorView
UIActivityIndicatorView *anActivityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
CGRect indicatorFrame = [anActivityIndicator frame];
indicatorFrame.origin = CGPointMake(200, 100);
anActivityIndicator.frame = indicatorFrame;
[anActivityIndicator setHidesWhenStopped:YES];
[anActivityIndicator startAnimating];
//[anActivityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.view addSubview:anActivityIndicator];
[anActivityIndicator release];
UIProgressView
-(void)viewDidLoad
{
UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
[self.view addSubview:progressView];
[progressView setTag:100];
[progressView setCenter:CGPointMake(200, 180)];
[progressView setProgress:0.5];
[progressView release];
[NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:@selector(progressBarChange:) userInfo:[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithFloat:0] forKey:@"ProgressValue"] repeats:YES];
}
- (void)progressBarChange:(NSTimer *)aTimer
{
NSMutableDictionary *userInfo = [aTimer userInfo];
float progressValue = [[userInfo objectForKey:@"ProgressValue"] floatValue];
[(UIProgressView *)[self.view viewWithTag:100] setProgress:progressValue];
progressValue += 0.1;
if( progressValue > 1.1f)
{
[aTimer invalidate];
}
[userInfo setObject:[NSNumber numberWithFloat:progressValue] forKey:@"ProgressValue"];
}
UILabel
-(void)viewDidLoad
{
UILabel *aLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 80, 150, 100)];
[aLabel setText:@"Sample Label asdasd asd as da "];
[aLabel setNumberOfLines:0];
[aLabel setBackgroundColor:[UIColor redColor]];
[aLabel setTextAlignment:UITextAlignmentRight];
[self.view addSubview:aLabel];
[aLabel release];
}
UIButton
-(void)viewDidLoad
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[aButton setTitle:@"BUTTON" forState:UIControlStateNormal];
[aButton setFrame:CGRectMake(20, 180, 150, 100)];
[self.view addSubview:aButton];
[aButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
UIImage *anImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/Images/bg_circle.png", [[NSBundle mainBundle] resourcePath]]];
//[aButton setImage:[UIImage imageNamed:@"Images/bg_circle.png"] forState:UIControlStateNormal];
[aButton setImage:anImage forState:UIControlStateNormal];
[anImage release];
}
- (void)buttonAction:(UIButton *)aButton
{
NSLog(@"BUTTON = %@", aButton);
[aButton setTitle:@"CLICKED" forState:UIControlStateNormal];
}
NSThread
*** code that should be run in the new thread goes here ***
[pool release];
}
NSTimer
Timers
1. First create the Timer
{
// Now I can access all the properties and methods of myObject [[timer userInfo]myObjectMethod];
}
myTimer = nil; // ensures we never invalidate an already invalid Timer
Basic Concepts in iPhone SDK
NSString and int
currentScoreLabel.text = [NSString stringWithFormat:@"%d", currentScore];Vibration and Sound
Here is how to make the phone vibrate (Note: Vibration does not work in the Simulator, it only works on the device.)AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Sound will work in the Simulator, however some sound (such as looped) has been reported as not working in Simulator or even altogether depending on the audio format. Note there are specific filetypes that must be used (.wav in this example).
Random Numbers
Time
Alerts
Plist files
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; myPlistPath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: @"%@.plist", plistName] ];
[myPlistPath retain]; // If it's not there, copy it from the bundle
NSFileManager *fileManger = [NSFileManager defaultManager];
if ( ![fileManger fileExistsAtPath:myPlistPath] )
{
NSString *pathToSettingsInBundle = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];
}
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *path = [documentsDirectoryPath stringByAppendingPathComponent:@"myApp.plist"];
NSMutableDictionary *plist = [NSDictionary dictionaryWithContentsOfFile: path];
myKey2 = (bool)[[plist valueForKey:@"myKey2"] boolValue];
[plist setValue:myKey forKey:@"myKey"];
[plist writeToFile:path atomically:YES];
Info button
Detecting Subviews
Tuesday, September 14, 2010
Casting
All About Casting
A few days ago Christopher & I chatted with an iPhone in Action reader about why Listing 18.3 in the book generated the warning "Warning: 'UIView' may not respond to -addPic:at:'". The answer is casting, and I think it's a topic that deserves some additional discussion.
All About Casting
Casting is a fundamental of C. Wikipedia defines it as an "explicit type conversion." We demonstrate it briefly on p.156, where we show that you can turn a float into an int with a little bit of casting magic:
float a = 6.00;
int b;
b = (int) a;
Beyond that, we give it pretty short attention. That's probably great for folks with experience with rigorous programming languages, but less useful for those of you just getting into them for the first time.
So in this article I'm going to talk more about casting by concentrating on three three times that I've seen it most in SDK development (and thus where you're most likely to encounter it). In order I'm going to cover: toll-free bridging; math casts; and, finally, method casts (the topic that got us started).
Toll-Free Bridging
This is the other cast-related topic that we covered pretty extensively in iPhone in Action. There are some details on p.157 (at the end of the discussion of casting) and on p.321 (in the "Using Core Fondation" box).
Much of your iPhone programming will be done using Cocoa frameworks, such as the UI and NS libraries. However, sometimes you'll have to instead use Apple's older libraries, such as Core Foundation. Core Foundation is object-oriented, just like the NS libraries, and as a result you end up with alternative ways to represent a lot of standard variable types. For example Core Foundation's CFStringRef and Cocoa's NSString * are alternate ways to represent strings.
Fortunately, Apple recognizes this equivalence and "toll-free bridges" equivalent Core Foundation and NS classes. In order to use one in the place of another, you just need to cast it, as we do throughout Listing 16.11 (pp.318-320):
(NSString *)ABRecordCopyCompositeName(thisPerson);
This sort of casting will come up frequently if you use older frameworks, such as Address Book and Core Graphics.
Math Casting
I've run into the most problem with casting when I was writing mathematical formulas. Listing 17.10 (pp.340-341) shows off one such examples. Most of the way through that example, you can see a line which reads:
int currentHeight = 395 - ceil((float)newLocation.altitude/savedDestinationHeight*(401-65));
Clearly, that's a cast, but I don't really explain why in the description of the code.
I had to cast because of the "int" variable that I'm saving the formula off to. A problem arises because there's not necessarily a consensus (among all programming languages) for how to treat the right-hand side of such an equation. Should the elements all be treated as integers, or should they be left in their native form until the final conversion is done? Apple's Objective-C appears to assume a conversion to the final variable type almost immediately.
In this situation that resulted in altitude/height being made into an integer before it was multiplied by 401-65, which was not the desired result, because I was trying to generate a percent (meaning that 0 or 1 was really not useful). Thus the cast of that division as a float.
I find this sort of thing to be the one situation where a cast is really required ... where leaving it out results in your program not working, and it can be very confusing to figure out why.
Method Casting
And so finally we come to query that started this article off. If you compile the code associated with Listing 18.3, you'll see "Warning: 'UIView' may not respond to -addPic:at:'". This is a non-fatal warning that has to do with yet another casting nuisance. You'll find the line that generates the warning at the top of p.353:
[self.view addPic:myImageView.image at:myImageView.frame];
If you think about it, the reason for this warning should jump out. The view controller's view property is defined as a UIView, which does not contain the addPic:at: method introduced in CollageView. Thus, if you don't like the warning, you can just cast the property appropriately:
[(collageView *)self.view addPic:myImageView.image at:myImageView.frame];
You can run into this sort of thing when a property or method assumes a very specific class of object, rather than the more general "id." If memory serves I also hit it when using the nextResponder method (probably in Listing 14.2 on p.247).
Some Final Words on Casting Warnings
It's important to note that casting problems will generally result in warnings.You don't have to resolve them. In particular a warning about uncasted toll-free bridging or a warning about an uncasted method isn't a problem as long as you know what you're doing. It's usually worth fixing them, just to make sure that you understand the reason for the warning, but you don't have to if you're doing something quick-and-dirty or have some reason to leave the warning in.
(In the case of the warning generated by Listing 18.3 we opted to leave out the casting to keep the code more readable, not really thinking about the fact that people might be concerned about the warning if they compiled the code.)
Much more insidious are the math-related casting problems which probably won't generate a warning at all. In my opinion, they're what you really have to watch out for--and they're also a good reason to generally be conscientious about casting all the time, so that you don't run into mystery problems without warnings when you get careless about math casts.
Common SDK Errors
Problems: My UIImage Doesn't Display on a Device!
One of the more frustrating problems that you can run into when developing for the iPhone is having everything work great on the simulator, but then fail when you load it onto a real device. One of the more common problems that shows up is when a UIImage that displayed on the simulator is missing on the iPhone.
Some folks trying to use the SplashScreen library have had this precise problem.
The problem is usually one of case. Your Macintosh is (probably) built on a case-independent file system. That means that if you try to load "Splash.png" when the filename is really "splash.png", it'll work fine.
Your iPhone is not case-independent, and thus it will fail to find the same file.
So, if you're unable to see a picture on an actual device, check the case of your file name first.
Monday, September 13, 2010
Touches Functions
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pnt = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint pnt = [touch locationInView:self.view];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint pnt = [touch locationInView:self.view];
}
UIScrollView
UIScrollView Image Gallery Tutorial
Using a UIScrollView to create a paging application seems to be a question I am frequently asked about. I decided to create this tutorial to show how you can create an image gallery with a UIScrollView. I will show you have to reuse two UIImageViews views to avoid creating a UIImageView for each image in the gallery. Full tutorial and source after the jump.
how to lift view up when keyboard is pressed?
{
const int movementDistance = 300;
const float movementDuration = 0.4f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
//in text field didbegin editing method call above one
- (void)textViewDidBeginEditing:(UITextView *)textField
{
if (txtField.frame.origin.y > 150)
[self animateTextField:textField up: YES];
}
//and when ever user pressed done button on keyboard for view to come down write below method
- (void)textViewDidEndEditing:(UITextView *)textField
{
if (txtField.frame.origin.y > 150)
[self animateTextField:textField up: NO];
}
NSUserDefaults
Saving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString [prefs setObject:@"TextToSave" forKey:@"keyToLookupString"];
// saving an NSInteger [prefs setInteger:42 forKey:@"integerKey"];
// saving a Double [prefs setDouble:3.1415 forKey:@"doubleKey"];
// saving a Float [prefs setFloat:1.2345678 forKey:@"floatKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut) [prefs synchronize];
Retrieving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString NSString *myString = [prefs stringForKey:@"keyToLookupString"];
// getting an NSInteger NSInteger myInt = [prefs integerForKey:@"integerKey"];
// getting an Float float myFloat = [prefs floatForKey:@"floatKey"];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
@"", kDefaultsUsernameKey,
@"", kDefaultsPasswordKey,
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[[NSUserDefaults standardUserDefaults] synchronize];
NSSet and NSMutableSet
NSSet *aSet = [NSSet alloc]initWithObjects
NSSet *aSet = [NSSet setWithObjects:@"one",@"two",@"three",nil];
[aSet initWithObjects:@"",@"",nil];
[aSet initWithSet:set2];
[aSet initWithArray:array];
//Count of an Set
[aSet count];
//Operations in Set
1.Intersection
[aSet intersectsSet:set2];
2.Union
[aSet unionSet:set2];
3.Remove Objects
[aSet removeObjects];
4.Minus
[aSet minusSet:set2];
//Adding Objects to the Set
NSMutableSet *mSet = [NSMutableSet setWithObjects:@"",nil];
[mSet setByAddingObject:@"Kumar"];
[mSet setByAddingObjectsFromSet:set2];
[mSet setByAddingObjectsFromArray:array];
NSDate
//To print Current date
NSLog(@"the date is %@",currentDate); //it displays with time
//How to add time to Date
[NSDate dateWithTimeIntervalSinceNow:60*60]; //It will add 1 hour to the present time
//How to manually give the Dates
[NSDate dateWithStrin]
//How to compare Dates
if([currentDate isEqualToDate:date2])
//print Description
[currentDate description];
NSNumber and NSDecimal Number
NSNumber *aNumber = [NSNumber numberWithInt:21];
NSNumber *aNumber = [NSNumber numberWithChar:'c'];
NSNumber *aNumber = [NSNumber numberWithBool:YES:];
NSNumber *aNumber = [NSNumber numberWithFloat:3.2:];
//How to print an number
NSLog(@"the number is %@",aNumber); //Done use %d because aNumber is an type Object
//How to convert aNumber to an Integer value
int x = [aNumber intValue];
float x = [aNumber floatValue];
BOOL x = [aNumber boolValue];
//How to add NSNumber value to the Array
NSArray *arr = [NSArray arrayWithObject:aNumber];
NSArray *arr = [NSArray arrayWithObject:x]; //wrong bcz x is an primitive data type
//NSDecimalNumber
//Mainly this class used for storing the decimal values
NSDecimalNumber *dNumber = [[NSDecimalNumber alloc]initWithString:@"23.3"];
NSDictionary
Objective-C Dictionary Object classes allow data to be stored and managed in the form of key-value pairs where both the key and the value are objects.
| Contents
• 1 What are Dictionary Objects? • 2 Creating Dictionary Objects • 3 Initializing and Adding Entries to a Dictionary Object • 4 Getting an Entry Count • 5 Accessing Dictionary Entries • 6 Removing Entries from a Dictionary Object |
|
|
|
|
What are Dictionary Objects?
In the previous chapter we looked at using array objects to store collections of objects. Dictionary objects fulfill a similar purpose except each object stored in the dictionary has associated with it a unique key (to be precise, the key is unique to the particular dictionary object). The unique key can be of any object type though to be useful they are typically string objects.
Objective-C dictionary objects are created using the NSDictionary and NSMutableDictionary classes. NSDictionary based objects are immutable (in other words once they have been created and initialized their contents cannot be modified). Mutable dictionaries are instantiated from the NSMutableDictionary class and may be modified after creation and initialization.
Creating Dictionary Objects
An empty, immutable dictionary object may be created as follows:
NSDictionary *bookListing = [NSDictionary dictionary];
Similarly, an empty mutable dictionary may be created as follows:
NSMutableDictionary *bookListing = [NSMutableDictionary dictionary];
Initializing and Adding Entries to a Dictionary Object
Each key-value pair contained within a dictionary is referred to as an entry. Once a relationship between a key and a value has been estabilshed that relationship cannot subsequently be modified.
New entries are added to a dictionary using the setObject instance method. This method takes as its arguments an object and a corresponding key:
NSMutableDictionary *bookListing = [NSMutableDictionary dictionary];
[bookListing setObject: @"Wind in the Willows" forKey: @"100-432112"];
[bookListing setObject: @"Tale of Two Cities " forKey: @"200-532874"];
[bookListing setObject: @"Sense and Sensibility" forKey: @"202-546549"];
[bookListing setObject: @"Shutter Island" forKey: @"104-109834"];
In the above example, the bookListing dictionary is initialized with four book names with corresponding reference codes to act as keys.
It is also possible to create and initialize a dictionary with a number of key-value pairs using the dictionaryWithObjectsAndKeys class method. For example, an alternative to the above code is as follows:
NSDictionary *bookListing = [NSDictionary dictionaryWithObjectsAndKeys: @"Wind in the Willows", @"100-432112", @"Tale of Two Cities ", @"200-532874", @"Sense and Sensibility", @"202-546549", @"Shutter Island", @"104-109834", nil];
Dictionaries may also be initialized using keys and values contained in arrays using the arrayWithObjects method:
NSArray *objectsArray = [NSArray arrayWithObjects: @"Wind in the Willows", @"Tale of Two Cities ", @"Sense and Sensibility", @"Shutter Island", nil];
NSArray *keysArray = [NSArray arrayWithObjects: @"100-432112", @"200-532874", @"202-546549", @"104-109834", nil];
NSDictionary *bookListing = [[NSDictionary alloc] initWithObjects: objectsArray forKeys: keysArray];
Getting an Entry Count
A count of the number of entries in a dictionary can be obtained using the count instance methods:
NSMutableDictionary *bookListing = [NSMutableDictionary dictionary];
int count;
[bookListing setObject: @"Wind in the Willows" forKey: @"100-432112"];
[bookListing setObject: @"Tale of Two Cities " forKey: @"200-532874"];
[bookListing setObject: @"Sense and Sensibility" forKey: @"202-546549"];
[bookListing setObject: @"Shutter Island" forKey: @"104-109834"];
NSLog (@"Number of books in dictionary = %i", [bookListing count]);
Accessing Dictionary Entries
Dictionary entries are accessed by referencing the key corresponding to the required entry via the objectForKey method. For example:
NSLog ( @"100-432112 = %@", [bookListing objectForKey: @"100-432112"]);
NSLog ( @"200-532874 = %@", [bookListing objectForKey: @"200-532874"]);
NSLog ( @"202-546549 = %@", [bookListing objectForKey: @"202-546549"]);
NSLog ( @"104-109834 = %@", [bookListing objectForKey: @"104-109834"]);
When combined with the previous code and executed, we would expect to see the following output:
100-432112 = Wind in the Willows
200-532874 = Tale of Two Cities
202-546549 = Sense and Sensibility
104-109834 = Shutter Island
Removing Entries from a Dictionary Object
Specific dictionary entries may be removed by referencing the key as an argument to the removeObjectForKey method. For example, to remove the book entry for "Shutter Island" we would write the following code:
[bookListing removeObjectForKey: @"104-109834"];
All entries in a dictionary may be removed using the removeAllObjects instance method:
[bookListing removeAllObjects];