15
Boutique product development company It is amazing what you can accomplish when you have a client-centric team to deliver outstanding products.

Ts archiving

  • Upload
    confiz

  • View
    543

  • Download
    2

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Ts   archiving

Boutique product development company It is amazing what you can accomplish when you have a client-centric team to deliver outstanding products.

Page 2: Ts   archiving

Archiving

Sajid Hussain | Software Evangelist

Page 3: Ts   archiving

Archiving Topics covered in the presentation

• Archiving With XML Property Lists

• Archiving With NS Keyed Archiver

• Writing Encoding and Decoding Methods

• Encoding and Decoding Basic Data Types in Keyed Archives

• Using NS Data to Create Custom Archives

• Using Archiver to Copy Objects

• Final Wrods

Sajid Hussain | Software Evangelist

Page 4: Ts   archiving

Archiving

Archiving

Sajid Hussain | Software Evangelist

Objective-C terms, archiving is the process of saving one or

more objects in a format so that they can later be restored.

Often this involves writing the object(s) to a file so it can

subsequently be read back in.

Page 5: Ts   archiving

Archiving

Archiving with XML Property Lists

Sajid Hussain | Software Evangelist

If your objects are of type NSString, NSDictionary, NSArray, NSDate, NSData, or NSNumber, you can use

the writeToFile:atomically: method implemented in these classes to write your data to a file.

Program # 1

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSDictionary*glossary = [NSDictionarydictionaryWithObjectsAndKeys:@”A class defined so other

classes can inherit from it.”, @”abstract class”, @”To implement all the methods defined in a

protocol”, @”adopt”, @”Storing an object for later use. “, @”archiving”, nil];

if ([glossary writeToFile: @”glossary”atomically: YES] == NO)

NSLog(@”Save to file failed!”);

[pool drain];

return 0;

}

The writeToFile:atomically: message is sent to your dictionary object glossary, causing the dictionary to be

written to the file glossary in the form of a property list. The atomically parameter is set to YES, meaning

that you want the write operation to be done to a temporary backup file first; once successful, the final data

is to be moved to the specified file named glossary.

Page 6: Ts   archiving

Archiving

Archiving with XML Property Lists Cont..

Sajid Hussain | Software Evangelist

If you examine the contents of the glossary file created by Program # 1, it looks

like this:

<?xml version=”1.0” encoding=”UTF-8”?>

<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN”“http://

www.apple.com/DTDs/PropertyList-1.0.dtd”>

<plist version=”1.0”>

<dict>

<key>abstract class</key>

<string>A class defined so other classes can inherit from it.</string>

<key>adopt</key>

<string>To implement all the methods defined in a

protocol</string><key>archiving</key>

<string>Storing an object for later use. </string>

</dict>

</plist>

Page 7: Ts   archiving

Archiving

Archiving with XML Property Lists Cont..

Sajid Hussain | Software Evangelist

Program # 2

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSDictionary*glossary;glossary = [NSDictionarydictionaryWithContentsOfFile:

@”glossary”];

for ( NSString *key in glossary )

NSLog(@”%@: %@”, key, [glossary objectForKey: key]);

[pool drain];

return 0;

}

Program # 2 Output

archiving: Storing an object for later use.

abstract class: A class defined so other classes can inherit from it.

adopt: To implement all the methods defined in a protocol

Page 8: Ts   archiving

Archiving

Archiving with NS Keyed Archiver

Sajid Hussain | Software Evangelist

Program # 3

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSDictionary*glossary = [NSDictionarydictionaryWithObjectsAndKeys: @”A class defined so other

classes can inherit from it”, @”abstract class”, @”To implement all the methods defined in a

protocol”, @”adopt”, @”Storing an object for later use”, @”archiving”, nil];

[NSKeyedArchiverarchiveRootObject: glossary toFile: @”glossary.archive”]; [pool release];

return 0;

}

Program # 4

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSDictionary*glossary;

glossary = [NSKeyedUnarchiverunarchiveObjectWithFile: @”glossary.archive”];

for ( NSString *key in glossary )

NSLog(@”%@: %@”, key, [glossary objectForKey: key]);

[pool drain];

return 0;

}

Program # 4 Output

abstract class: A class defined so other classes can inherit from it.

adopt: To implement all the methods defined in a protocol

archiving: Storing an object for later use.

Page 9: Ts   archiving

Archiving

Writing Encoding and Decoding Method

Sajid Hussain | Software Evangelist

Basic Objective-C class objects such as NSString, NSArray, NSDictionary, NSSet, NSDate,NSNumber, and NSData

can be archived and restored in the manner just described. That includes nested objects as well, such as an array

containing a string or even other array objects. To archive objects other than those listed, you must tell the system how

to archive, or encode, your objects, and also how to unarchive, or decode, them. This is done by adding

encodeWithCoder: and initWithCoder: methods to your class definitions, according to the <NSCoding> protocol.

@interface Foo: NSObject<NSCoding>{

NSString*strVal; intintVal; float floatVal;

}

@property (copy, nonatomic) NSString *strVal;

@property intintVal;

@property float floatVal;

@end

// Definition for our Fooclass

@implementation Foo

@synthesize strVal, intVal, floatVal;

-(void) encodeWithCoder: (NSCoder *) encoder {

[encoder encodeObject: strValforKey: @”FoostrVal”];

[encoder encodeInt: intValforKey: @”FoointVal”];

[encoder encodeFloat: floatValforKey: @”FoofloatVal”];

}

-(id) initWithCoder: (NSCoder *) decoder {

strVal= [[decoder decodeObjectForKey: @”FoostrVal”] retain];

intVal= [decoder decodeIntForKey: @”FoointVal”];

floatVal= [decoder decodeFloatForKey: @”FoofloatVal”];

return self;

Page 10: Ts   archiving

Archiving

Writing Encoding and Decoding Method Cont..

Sajid Hussain | Software Evangelist

Program # 5Test Program

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

Foo*myFoo1 = [[Fooalloc] init];

Foo*myFoo2;[myFoo1 setStrVal: @”This is the string”];

[myFoo1 setIntVal: 12345];

[myFoo1 setFloatVal: 98.6];

[NSKeyedArchiver archiveRootObject: myFoo1 toFile: @”foo.arch”];

myFoo2 = [NSKeyedUnarchiverunarchiveObjectWithFile: @”foo.arch”];

NSLog(@”%@\n%i\n%g”, [myFoo2 strVal], [myFoo2 intVal], [myFoo2 floatVal]);

[myFoo1 release];

[pool drain];

return 0;

}

Program # 5 Output

This is the string

12345

98.6

The encodeWithCoder: method is invoked each time the archiver wants to encode an object from the specified class,

and the method tells it how to do so. In a similar manner, the initWithCoder: method is invoked each time an object from

the specified class is to be decoded. if you knew the super- class of your class conformed to the NSCoding protocol,

you should start your encoding method with a statement like the following to make sure your inherited instance

variables are encoded: [super encodeWithCoder: encoder]; The only time a conflict might arise is if the same key is

used for a subclass of an object being encoded. To prevent this from happening, you can insert the class name in front

of the instance variable name when composing the key for the archive.

Page 11: Ts   archiving

Archiving

Encoding and Decoding Basic Data Types in Keyed Archives

Sajid Hussain | Software Evangelist

Encoder Decoder

encodeBool:forKey: decodeBool:forKey:

encodeInt:forKey: decodeInt:forKey:

encodeInt32:forKey: decodeInt32:forKey:

encodeInt64: forKey: decodeInt64:forKey:

encodeFloat:forKey: decodeFloat:forKey:

encodeDouble:forKey: decodeDouble:forKey:

For basic underlying C data types (such as integers and floats), you use one of the methods listed in the following

Table. The decoder method, initWithCoder: works in reverse: You use decodeObject:forKey: to decode basic Objective-

C classes and the appropriate decoder method shown in following Table for the basic data types.

Some of the basic data types, such as char, short, long, and long long, are not listed in the Table; you must determine

the size of your data object and use the appropriate routine. For example, a short int is normally 16 bits, an int and long

can be 32 or 64 bits, and a long long is 64 bits. (You can use the sizeof operator to determine the size of any data type.)

So to archive a short int, store it in an int first and then archive it with encodeInt:forKey:. Reverse the process to get it

back: Use decodeInt:forKey: and then assign it to your short int variable.

Page 12: Ts   archiving

Archiving

Using NSData to Create Custom Archives

Sajid Hussain | Software Evangelist

Perhaps you want to collect some or all of your objects and store them in a single archive file.

Program # 6

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

Foo*myFoo1 = [[Fooalloc] init];

NSMutableData*dataArea;NSKeyedArchiver *archiver;

[myFoo1 setStrVal: @”This is the string”];

[myFoo1 setIntVal: 12345];

[myFoo1 setFloatVal: 98.6];

// Set up a data area and connect it to an NSKeyedArchiver object

dataArea= [NSMutableData data];

archiver= [[NSKeyedArchiveralloc] initForWritingWithMutableData: dataArea];

// Now we can begin to archive objects

[archiverencodeObject: myFoo1 forKey: @”myfoo1”];

[archiverfinishEncoding];

// Write the archived data are to a file

if ( [dataAreawriteToFile: @”myArchive” atomically: YES] == NO)

NSLog(@”Archiving failed!”);

[archiver release];

[myFoo1 release];

[pool drain];

return 0;

Page 13: Ts   archiving

Archiving

Using NSData to Create Custom Archives Cont..

Sajid Hussain | Software Evangelist

Program # 7

intmain (intargc, char *argv[]) {

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSData*dataArea;

NSKeyedUnarchiver*unarchiver;

Foo*myFoo1;

// Read in the archive and connect an NSKeyedUnarchiver object to it

dataArea= [NSDatadataWithContentsOfFile: @”myArchive”];

if (! dataArea) {

NSLog(@“Can’t read back archive file!”);

Return (1);

}

unarchiver= [[NSKeyedUnarchiveralloc] initForReadingWithData: dataArea];

// Decode the objects we previously stored in the archive

myFoo1 = [unarchiverdecodeObjectForKey: @”myfoo1”];

[unarchiver finishDecoding];

[unarchiver release];

// Verify that the restore was successful

} NSLog(“%@\n%i\n%g”, [myFoo1 strVal], [myFoo1 intVal], [myFoo1 floatVal]);

[pool release];

return 0;

Page 14: Ts   archiving

Archiving

Using Archiver to Copy Objects

Sajid Hussain | Software Evangelist

Program # 8

intmain (intargc, char *argv[]) {

NSAutoreleasePool*pool = [[NSAutoreleasePoolalloc] init];

NSData*data;

NSMutableArray*dataArray = [NSMutableArrayarrayWithObjects:[NSMutableStringstringWithString: @”one”],

[NSMutableStringstringWithString: @”two”], [NSMutableStringstringWithString: @”three”], nil];

NSMutableArray*dataArray2;

NSMutableString*mStr;

// Make a deep copy using the archiver

data = [NSKeyedArchiverarchivedDataWithRootObject: dataArray];

dataArray2 = [NSKeyedUnarchiverunarchiveObjectWithData: data];

mStr= [dataArray2 objectAtIndex: 0];

[mStrappendString: @”ONE”];

NSLog(@”dataArray: “);

for ( NSString *elem in dataArray)

NSLog(“%@”, elem);

NSLog(@”\ndataArray2: “);

for ( NSString *elem in dataArray2 )

NSLog(“%@”, elem);

[pool drsin];

return 0;

}

Program # 8 Output

dataArray:

one

two

Three

dataArray2:

oneONE

two

three

Page 15: Ts   archiving

Archiving

Final Words

Sajid Hussain | Software Evangelist

• If you want to store simple values, serialization (using an

NSDictionary, for example) is a fine way to go. If you want to store

an object graph of arbitrary types, with uniqueness and mutability

preserved, using archives (with NSCoder, for example) is your best

bet.

• NSCodingis a powerful way to serialize objects so that you can

pass them between processes or save it to a file. Implement the

NSCoding protocol on your custom objects that you want to

serialize, then use NSKeyedArchiver to serialize them and

NSKeyedUnarchiver to deserialize them.