psineur / NSObject-AutomagicCoding

Ability to save every object to PLIST without any special coding.
Other
237 stars 35 forks source link

AMC

AMC is AutoMagic Coding - very easy to use NSCoding replacement for Mac & iOS Projects. AMC gives you ability to create NSDictionary representation of any supported object, save it in PLIST (or any other PLIST-compatible file format, i.e. JSON) and load again without writing a lot of code.

AMC uses Objective-C Runtime to determine object's properties automatically & Key-Value-Coding to get & set them.

Repo Contents

Supported properties types

File Format


AMC saves object to NSDictionary, that can be saved to PLIST (or JSON).
Keys simply are ivars names and/or properties names.
One special key ( "class" ) used to hold name of the object's class.
Run unit tests on Mac & go look to your Documents folder - there will be a lot of PLISTs.
They are test objects saved to PLIST files.

Known Issues

How To Use

  1. Drag'n'Drop NSObject+AutoMagicCoding.h | m to your project. This will add AMC methods to all objects inherited from NSObject.
  2. Import NSObject+AutoMagicCoding.h where you need it.
  3. Reimplement +(BOOL)AMCEnabled and return YES to enable AMC for all instances of your class.
  4. Reimplement -(id)initWithDictionaryRepresentation: and use [super initWithDictionaryRepresentation] inside of it. Ensure that all collections & other fields are created after calling super initWithDictionaryRepresentation. Do your own init routines after.
  5. Use -dictionaryRepresentation to encode your object to NSDictionary & NSObject::objectWithDictionaryRepresentation: to decode.

    • Additionaly: reimplement -AMCKeysForDictionaryRepresentation to change amount & order of encoded/decoded fields. (See AMCKeysForDictionaryRepresentation below for more info ).
    • Additionaly: reimplement -AMCEncodeStructWithValue:withName: & -AMCDecodeStructWithValue: withName: to support custom structs (See Custom Struct below for more info).
    • Additionaly: reimplement -AMCFieldTypeForValueWithKey: for any non-scalar ivars, that you want to use as fields for AMC.

    ATTENTION: It's recommended to avoid using iVars without properties in AMC due to harder memory management, need to write more code, unsupported custom structs & possible future restrictions.

AMCKeysForDictionaryRepresentation
==================

-AMCKeysForDictionaryRepresentation returns NSArray of NSStrings, thar are passed to KVC methods to get & set fields of AMCEnabled objects. Default implementation returns complete set of all object properties (both readonly & readwrite), including properties declared by superclasses (NSObject's properties are not included). Reimplement this method to choose manually, what properties should be encoded/decoded by AMC. See tests in "Tests" folder for more info & usage examples.

Custom Struct Support
==================

To support your own custom structs you must do the following:

  1. Your custom structs should be used ONLY AS PROPERTIES in your classes. iVars custom structs are not supported.
  2. Reimplement -AMCEncodeStructWithValue:withName: & AMCDecodeStructFromString:withName: like this:
- (NSString *) AMCEncodeStructWithValue: (NSValue *) structValue withName: (NSString *) structName
{
    if ([structName isEqualToString: @"CustomStruct" ])
    {
        CustomStruct custom;
        [structValue getValue: &custom]; 

        return NSStringFromCustomStruct(custom);
    }

    return [super AMCEncodeStructWithValue: structValue withName: structName];
}

- (NSValue *) AMCDecodeStructFromString: (NSString *)value withName: (NSString *) structName
{
    if ([structName isEqualToString: @"CustomStruct" ])
    {
        CustomStruct custom = CustomStructFromNSString(value);
        return [NSValue valueWithBytes: &custom objCType:@encode(CustomStruct)];
    }

    return [super AMCDecodeStructFromString: value withName: structName];
}

See FooWithStructs & AMCTestSimple for working example.

Exceptions

All exceptions, bad-data & unwanted behaviour tests are located in AMCExceptions.m.

Here's a list of bad things, that can happen with AMC:

AMC_NO_THROW

You can define AMC_NO_THROW to disable exceptions throw by following methods:

With AMC_NO_THROW defined they will simply return nil and/or do nothing instead.
-AMCDecodeStructFromString:withName: & -AMCEncodeStructWithValue:withName: can throw exceptions even if AMC_NO_THROW is defined. Don't catch any exceptions in your reimplementations of these methods - you don't need to call them directly, so AMC will catch their exceptions for you.

License

AMC is licensed under terms & conditions of MIT License.
http://www.opensource.org/licenses/mit-license.php

Copyright 2011 Stepan Generalov.

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.