Lagra data
Finns många sätt NSUserDefaults Property Lists Archiving CoreData SQLite Web Services... Vi kommer denna gång att titta på Property Lists och Archiving + lite hur man kan göra skriva text och binär data.
Filer på iphone Varje applikation har en egen katalog på telefonen. Applikationer får endast skriva till/läsa filer i sin egen katalog (närmare bestämt i någon av katalogerna Documents, Library, och tmp i denna) I simulatorn hittar man igen en applikations filer i katalogen ~/Library/Application Support/iPhone Simulator/User/Applications/<App_ID>
En applikations kataloger Kataloger i en applikations katalog. Documents och Preferences görs backup på.
Fixa en sökväg till de olika katalogerna Ta fram sökväg till en fil i Documents katalogen // Hämta listan över dokumentkataloger NSArray *documentdirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);! /* Hämta den enda dokumentkatalogen från listan (finns flera i MacOSX därav returnerar funktionen en array)*/ NSString *documentdirectory = [documentdirectories objectatindex:0];!! // Lägg till filnamnet NSString * fullpath=[documentdirectory stringbyappendingpathcomponent: filename];
Textfiler I NSString finns metoder för att skriva data - (BOOL)writeToFile:(NSString *)path atomically:(bool)useauxiliaryfile encoding: (NSStringEncoding)enc error:(nserror **)error... och för att läsa in det - (id)initwithcontentsoffile:(nsstring *)path encoding:(nsstringencoding)enc error:(nserror **)error;
Exempel NSString *str=@"hello World"; NSError *err; [str writetofile: path!! atomically: YES!!! encoding: NSUTF8StringEncoding!!! error: &err];
Binärfiler NSData Klass för att hantera binärdata -(BOOL)writeToFile:(NSString*) path atomically:(bool) (id) initwithcontentsoffile:(nsstring *) path;
Andra sätt Text och binärfiler i form av att skriva mha metoderna i NSString och NSData passar kanske inte så jättebra då vi har lite mer strukturerat data (som tex objekt som vi kan lagra undan). Vi kommer att titta på två sätt denna gång nämligen plists och archiving.
PLists Följande typer av data kan lagras i plists (property list) NSData, NSString, NSNumber, NSArray, NSDictionary Vi kan alltså fylla en NSArray eller NSDictionary med data (Så länge alla dessa kan lagras i en plist och sedan läsa tillbaka arrayen.
Exempel på att skriva till plist NSMutableDictionary *nsdict=[nsmutabledictionary dictionary]; [nsdict setobject:@"johan Eliasson" forkey: @"Name"]; [nsdict setobject:@"070-2378xxx" forkey: @"Phone"]; [nsdict writetofile:path atomically: YES]; //Och för att läsa tillbaka datat NSMutableDictionary *nsdict=[[nsmutabledictionary alloc] initwithcontentsoffile:path];
Archiving Används av XIB-filer (eg dessa är egentligen bara objekt som lagrats på fil) Kan användas för att spara undan grafer med sammanhängande objekt, För att få detta att fungera för egna klasser måste man låta klasserna implementera protokollet NSCoding NSCoding protokollet kräver att två metoder finns - (void)encodewithcoder:(nscoder *)encoder - (id)initwithcoder:(nscoder *)decoder
Klasser som implementerar NSCoding Många inbyggda klasser tex NSString, NSArray, NSDictionary, NSNumber, och de flesta användargränssnittsklasserna implementerar NSCoding och kan därför arkiveras. Se i dokumentationen för respektive klass om de implementerar NSCoding
Koda data När ett objekt tar emot meddelandet encodewithcoder: ska det koda alla attribut som den behöver spara för att kunna återskapas efter att ha skickat vidare meddelandet till sin superklass om denna implementerar NSCoding protokollet. För att koda attributen använder man metoderna för att koda data i NSCoder encode...: forkey: Observera att det inte är nödvändigt att spara alla attribut i alla situationer. Vissa värden är kanske inte viktiga för att kunna återställa tillståndet vid avkodningen.
Avkodning När ett objekt tar emot meddelandet initwithcoder: ska det först skicka meddelandet vidare till superklassen om denna implementerar NSCoding (eller annars anropa superklassens konstruktor) för att initiera ärvda attribut. Efter de ska den avkoda sina egna attribut. Använde man sig av forkey: metoderna i NSCoder för kodningen (rekommenderas) så kan avkodningen av attributen ske i vilken ordning som helst.
Exempel @interface Rectangle : NSObject <NSCoding> {! int width;! int height; }
encodewithcoder: -(void) encodewithcoder: (NSCoder *) encoder {! [encoder encodeint:width forkey:@"width"];! [encoder encodeint:height forkey:@"height"]; }
initwithcoder: -(id) initwithcoder: (NSCoder *) decoder { [super init];! //Kom ihåg att ev. objekt måste retainas! width=[decoder decodeintforkey: @"width"];! height=[decoder decodeintforkey: @"height"];!return self; }
NSCoder: urval av metoder för att koda data encodeint:forkey: Motsvarande metoder finns för double, float, BOOL encodeinteger:forkey: För NSInteger encodeobject:forkey: För att hantera andra objekt som implementerar NSCoding encoderootobject: För att koda startobjektet i grafen Det finns fler metoder kolla gärna dokumentationen för NSCoder
NSCoder: urval av metoder för att avkoda data decodeintforkey: Motsvarande metoder finns för double, float, BOOL decodeobjectforkey:
Läsa/skriva datat till fil Görs med klassen NSKeyedArchiver Exempel på att skriva: [NSKeyedArchiver archiverootobject:myobject tofile:filepath]; Exempel på att läsa in: myobject=[nskeyedunarchiver unarchiveobjectwithfile:filepath]; [myobject retain];