diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2ec406f --- /dev/null +++ b/.travis.yml @@ -0,0 +1 @@ +language: objective-c \ No newline at end of file diff --git a/Archiver.h b/Archiver.h index a905107..8b20f07 100644 --- a/Archiver.h +++ b/Archiver.h @@ -10,7 +10,7 @@ @interface Archiver : NSObject { - + } + (id)retrieve:(NSString *)key; diff --git a/Archiver.m b/Archiver.m index ff38994..73f6124 100644 --- a/Archiver.m +++ b/Archiver.m @@ -14,7 +14,7 @@ + (id)retrieve:(NSString *)key { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filePath = [documentsDirectory stringByAppendingString:[NSString stringWithFormat:@"/%@.archive", key]]; - return [[[NSKeyedUnarchiver unarchiveObjectWithFile:filePath] retain] autorelease]; + return [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; } + (BOOL)persist:(id)object key:(NSString *)key { @@ -29,7 +29,7 @@ + (BOOL)delete:(NSString *)key { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filePath = [documentsDirectory stringByAppendingString:[NSString stringWithFormat:@"/%@.archive", key]]; - return [fileManager removeItemAtPath:filePath error:NULL]; + return [fileManager removeItemAtPath:filePath error:NULL]; } + (BOOL)deleteEverything { diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c0e9839 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013 NSObject-NSCoding-Kingiol + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/NSObject+NSCoding.m b/NSObject+NSCoding.m index b7bf528..c598cfe 100644 --- a/NSObject+NSCoding.m +++ b/NSObject+NSCoding.m @@ -14,7 +14,7 @@ @implementation NSObject (NSCoding) - (NSMutableDictionary *)propertiesForClass:(Class)klass { - NSMutableDictionary *results = [[[NSMutableDictionary alloc] init] autorelease]; + NSMutableDictionary *results = [[NSMutableDictionary alloc] init]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(klass, &outCount); @@ -68,7 +68,10 @@ - (void)autoEncodeWithCoder:(NSCoder *)coder { if ([[type componentsSeparatedByString:@"\""] count] > 1) { className = [[type componentsSeparatedByString:@"\""] objectAtIndex:1]; Class class = NSClassFromString(className); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" value = [self performSelector:NSSelectorFromString(key)]; +#pragma clang diagnostic pop // only decode if the property conforms to NSCoding if([class conformsToProtocol:@protocol(NSCoding)]){ @@ -123,7 +126,7 @@ - (void)autoEncodeWithCoder:(NSCoder *)coder { break; default: break; - } + } } } @@ -133,7 +136,6 @@ - (void)autoDecode:(NSCoder *)coder { NSString *type = [properties objectForKey:key]; id value; NSNumber *number; - unsigned int addr; NSInteger i; CGFloat f; BOOL b; @@ -143,81 +145,66 @@ - (void)autoDecode:(NSCoder *)coder { long longValue; unsigned unsignedValue; short shortValue; - Ivar ivar; - double *varIndex; NSString *className; switch ([type characterAtIndex:0]) { case '@': // object if ([[type componentsSeparatedByString:@"\""] count] > 1) { - className = [[type componentsSeparatedByString:@"\""] objectAtIndex:1]; + className = [[type componentsSeparatedByString:@"\""] objectAtIndex:1]; Class class = NSClassFromString(className); // only decode if the property conforms to NSCoding if ([class conformsToProtocol:@protocol(NSCoding )]){ - value = [[coder decodeObjectForKey:key] retain]; - addr = (NSInteger)&value; - object_setInstanceVariable(self, [key UTF8String], *(id**)addr); + value = [coder decodeObjectForKey:key]; + [self setValue:value forKey:key]; } } break; case 'c': // bool - number = [coder decodeObjectForKey:key]; + number = [coder decodeObjectForKey:key]; b = [number boolValue]; - addr = (NSInteger)&b; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(b) forKey:key]; break; case 'f': // float - number = [coder decodeObjectForKey:key]; + number = [coder decodeObjectForKey:key]; f = [number floatValue]; - addr = (NSInteger)&f; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(f) forKey:key]; break; - case 'd': // double + case 'd': // double number = [coder decodeObjectForKey:key]; d = [number doubleValue]; - if ((ivar = class_getInstanceVariable([self class], [key UTF8String]))) { - varIndex = (double *)(void **)((char *)self + ivar_getOffset(ivar)); - *varIndex = d; - } + [self setValue:@(d) forKey:key]; break; case 'i': // int number = [coder decodeObjectForKey:key]; i = [number intValue]; - addr = (NSInteger)&i; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(i) forKey:key]; break; case 'L': // unsigned long number = [coder decodeObjectForKey:key]; ul = [number unsignedLongValue]; - addr = (NSInteger)&ul; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(ul) forKey:key]; break; case 'Q': // unsigned long long number = [coder decodeObjectForKey:key]; ull = [number unsignedLongLongValue]; - addr = (NSInteger)&ull; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(ull) forKey:key]; break; case 'l': // long number = [coder decodeObjectForKey:key]; longValue = [number longValue]; - addr = (NSInteger)&longValue; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(longValue) forKey:key]; break; case 'I': // unsigned number = [coder decodeObjectForKey:key]; unsignedValue = [number unsignedIntValue]; - addr = (NSInteger)&unsignedValue; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(unsignedValue) forKey:key]; break; case 's': // short number = [coder decodeObjectForKey:key]; shortValue = [number shortValue]; - addr = (NSInteger)&shortValue; - object_setInstanceVariable(self, [key UTF8String], *(NSInteger**)addr); + [self setValue:@(shortValue) forKey:key]; break; - default: break; } diff --git a/NSObject-NSCoding.podspec b/NSObject-NSCoding.podspec new file mode 100644 index 0000000..87d97ca --- /dev/null +++ b/NSObject-NSCoding.podspec @@ -0,0 +1,12 @@ +Pod::Spec.new do |s| + s.name = "NSObject-NSCoding" + s.version = "1.0" + s.summary = "Automatic NSCoding and persistence implementation" + s.homepage = "https://github.com/kingiol/NSObject-NSCoding" + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { "greenisus" => "greenisus@gmail.com", "kingiol" => "kingxiaokang@gmail.com" } + s.platform = :ios + s.source = { :git => "https://github.com/kingiol/NSObject-NSCoding.git", :tag => "1.0" } + s.source_files = '*.{h,m}' + s.requires_arc = true +end \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index 1fe586f..0000000 --- a/README +++ /dev/null @@ -1,60 +0,0 @@ -NSObject+NSCoding and Archiver ------------------------------- - -Mike Mayo -Rackspace Mobile Apps -mike@overhrd.com -twitter: @greenisus - -These are some simple classes to make object persistence with NSCoding easier. This code was extracted from -the Rackspace Cloud / OpenStack iOS app at http://launchpad.net/openstack-ios - -INSTALLATION - -To install, simply drag Archiver.h, Archiver.m, NSObject+NSCoding.h, and NSObject+NSCoding.m into your project. - -Then, right click Frameworks in Groups & Files and choose Add -> Existing Frameworks... and choose libobjc.A.dylib. - -USAGE - --- Archiver - -This class will read and write objects that conform to the NSCoding protocol to disk. - -Archiver Usage: - -SomeClass *myObject = [[[SomeClass alloc] init] autorelease]; -myObject.someProperty = @"Hello world"; - -[Archiver persist:myObject key:@"myObject"]; - -// later on somewhere else... - -SomeClass *myObject = [Archiver retrieve:@"myObject"]; - --- NSObject+NSCoding - -This category simplifies implementing NSCoding by iterating over the properties of your -class and encoding/decoding them for you. It persists primitives (such as ints and floats) -as well as any objects that conform to NSCoding. - -NSObject+NSCoding Usage: - -In your class header, conform to NSCoding: - -@interface Model : NSObject { -//... -} - -In your class implementation, call the automatic methods: - -- (void)encodeWithCoder:(NSCoder *)coder { - [self autoEncodeWithCoder:coder]; -} - -- (id)initWithCoder:(NSCoder *)coder { - if (self = [super init]) { - [self autoDecode:coder]; - } - return self; -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec1bbe9 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +NSObject+NSCoding and Archiver +------------------------------ + +build by Kingiol + +[![Build Status](https://travis-ci.org/kingiol/NSObject-NSCoding.png?branch=master)](https://travis-ci.org/kingiol/NSObject-NSCoding) + +Mike Mayo +Rackspace Mobile Apps +mike@overhrd.com +twitter: @greenisus + +These are some simple classes to make object persistence with NSCoding easier. This code was extracted from +the Rackspace Cloud / OpenStack iOS app at http://launchpad.net/openstack-ios + +# Installation + +CocoaPods +- + +NSObject-NSCoding is easiest to install using [CocoaPods](http://cocoapods.org). +Simply add this line to your Podfile + + pod 'NSObject-NSCoding' + +and run `pod install` + +Static +- + +If you prefer not to use CocoaPods, simply drag `Archiver.h`, `Archiver.m`, `NSObject+NSCoding.h`, and `NSObject+NSCoding.m` into your project. + +Then, right click `Frameworks` in `Groups & Files` and choose `Add` -> `Existing Frameworks...` and choose `libobjc.A.dylib`. + +# Usage + +Archiver +- + +This class will read and write objects that conform to the NSCoding protocol to disk. + + SomeClass *myObject = [[[SomeClass alloc] init] autorelease]; + myObject.someProperty = @"Hello world"; + + [Archiver persist:myObject key:@"myObject"]; + + // later on somewhere else... + + SomeClass *myObject = [Archiver retrieve:@"myObject"]; + +NSObject+NSCoding +- + +This category simplifies implementing NSCoding by iterating over the properties of your +class and encoding/decoding them for you. It persists primitives (such as ints and floats) +as well as any objects that conform to NSCoding. + +In your class header, conform to NSCoding: + + @interface Model : NSObject + +In your class implementation, call the automatic methods: + + - (void)encodeWithCoder:(NSCoder *)coder { + [self autoEncodeWithCoder:coder]; + } + + - (id)initWithCoder:(NSCoder *)coder { + if (self = [super init]) { + [self autoDecode:coder]; + } + return self; + } + +# License + +NSObject+NSCoding is released under the MIT license. A full description of that license is available in the LICENSE file.