- Fix PNInstallation

This commit is contained in:
Giuseppe Nucifora 2016-04-08 14:18:29 +02:00
parent 8ad99ddd70
commit 2e2ed83e95
47 changed files with 5914 additions and 3778 deletions

View File

@ -120,6 +120,8 @@
NSLog(@"%@",installation);
NSLog(@"%@",[installation JSONFormObject]);
}
- (void) application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {

View File

@ -43,12 +43,12 @@ PODS:
- JRSwizzle (1.0)
- NACrypto (1.0.6)
- NSDate_Utils (0.1.3)
- NSString-Helper (1.0.4)
- NSString-Helper (1.0.5)
- NSUserDefaults-AESEncryptor (0.0.4):
- CocoaSecurity (~> 1.2.2)
- nv-ios-http-status (0.0.1)
- PEAR-FileManager-iOS (1.3.1)
- PNObject (0.5.6):
- PNObject (0.5.7):
- AFNetworking
- CodFis-Helper
- DJLocalization
@ -61,9 +61,11 @@ PODS:
- NSUserDefaults-AESEncryptor
- nv-ios-http-status
- PEAR-FileManager-iOS
- RZDataBinding
- StrongestPasswordValidator
- UIDevice-Utils
- PureLayout (3.0.1)
- RZDataBinding (2.0.3)
- Specta (1.0.5)
- StrongestPasswordValidator (0.1.2)
- UIDevice-Utils (0.1.5)
@ -106,12 +108,13 @@ SPEC CHECKSUMS:
JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3
NACrypto: ce3900f1775f1b0cc27ce7c4953b94c598a74149
NSDate_Utils: 68669d2c81f310ee13026c791f4f0ed227b94c65
NSString-Helper: b4183f73f0a00c6fcd607edebb6c35a7a461376d
NSString-Helper: 459e1b6a62b3bf7db10f01b0d102548608e945c4
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
PNObject: 2bb4603ecbce2116013d23c6bd7f16da73c0e57b
PNObject: 9567f1c80c154eb17798e2b9f572a707c407d7b5
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
RZDataBinding: 00d468ebe667f02c2bd5416f87b4b5d826188c4d
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
UIDevice-Utils: a87bbaed53a74d503deb3e25511c9a4d865b92ea

View File

@ -0,0 +1 @@
../../../RZDataBinding/RZDataBinding/NSObject+RZDataBinding.h

View File

@ -0,0 +1 @@
../../../RZDataBinding/RZDataBinding/RZDBCoalesce.h

View File

@ -0,0 +1 @@
../../../RZDataBinding/RZDataBinding/RZDBMacros.h

View File

@ -0,0 +1 @@
../../../RZDataBinding/RZDataBinding/RZDBTransforms.h

View File

@ -0,0 +1 @@
../../../RZDataBinding/RZDataBinding/RZDataBinding.h

View File

@ -1,6 +1,6 @@
{
"name": "PNObject",
"version": "0.5.6",
"version": "0.5.7",
"summary": "PNObject is a simple replica of the more complex ParseObject",
"homepage": "https://github.com/giuseppenucifora/PNObject",
"license": "MIT",
@ -9,7 +9,7 @@
},
"source": {
"git": "https://github.com/giuseppenucifora/PNObject.git",
"tag": "0.5.6"
"tag": "0.5.7"
},
"platforms": {
"ios": "8.0"
@ -58,6 +58,9 @@
],
"DJLocalization": [
],
"RZDataBinding": [
]
}
}

View File

@ -43,12 +43,12 @@ PODS:
- JRSwizzle (1.0)
- NACrypto (1.0.6)
- NSDate_Utils (0.1.3)
- NSString-Helper (1.0.4)
- NSString-Helper (1.0.5)
- NSUserDefaults-AESEncryptor (0.0.4):
- CocoaSecurity (~> 1.2.2)
- nv-ios-http-status (0.0.1)
- PEAR-FileManager-iOS (1.3.1)
- PNObject (0.5.6):
- PNObject (0.5.7):
- AFNetworking
- CodFis-Helper
- DJLocalization
@ -61,9 +61,11 @@ PODS:
- NSUserDefaults-AESEncryptor
- nv-ios-http-status
- PEAR-FileManager-iOS
- RZDataBinding
- StrongestPasswordValidator
- UIDevice-Utils
- PureLayout (3.0.1)
- RZDataBinding (2.0.3)
- Specta (1.0.5)
- StrongestPasswordValidator (0.1.2)
- UIDevice-Utils (0.1.5)
@ -106,12 +108,13 @@ SPEC CHECKSUMS:
JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3
NACrypto: ce3900f1775f1b0cc27ce7c4953b94c598a74149
NSDate_Utils: 68669d2c81f310ee13026c791f4f0ed227b94c65
NSString-Helper: b4183f73f0a00c6fcd607edebb6c35a7a461376d
NSString-Helper: 459e1b6a62b3bf7db10f01b0d102548608e945c4
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
PNObject: 2bb4603ecbce2116013d23c6bd7f16da73c0e57b
PNObject: 9567f1c80c154eb17798e2b9f572a707c407d7b5
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
RZDataBinding: 00d468ebe667f02c2bd5416f87b4b5d826188c4d
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
UIDevice-Utils: a87bbaed53a74d503deb3e25511c9a4d865b92ea

View File

@ -10,6 +10,8 @@
@interface NSString (Helper)
+ (NSString *) getRandString: (int) length;
- (BOOL) isValidEmail;
- (BOOL) isNumeric;
@ -20,4 +22,12 @@
- (BOOL) isValidTaxCode;
- (NSString *) md5;
- (NSString*) sha1;
- (NSString*) sha256;
- (NSString*) sha512;
@end

View File

@ -7,6 +7,7 @@
//
#import "NSString+Helper.h"
#import <CommonCrypto/CommonDigest.h>
@implementation NSString (Helper)
@ -58,4 +59,84 @@
return [urlTest evaluateWithObject:self];
}
#pragma mark - Random String Method
+ (NSString *) getRandString: (int) length {
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity: length];
for (int i=0; i<length; i++) {
[randomString appendFormat: @"%C", [letters characterAtIndex: arc4random() % [letters length]]];
}
return randomString;
}
- (NSString *) md5 {
const char *cStr = [self UTF8String];
unsigned char digest[16];
CC_MD5( cStr, (CC_LONG)strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
- (NSString*) sha1 {
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
- (NSString*) sha256 {
const char *s=[self cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData=[NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH]={0};
CC_SHA256(keyData.bytes, (CC_LONG)keyData.length, digest);
NSData *out=[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
NSString *hash=[out description];
hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""];
return hash;
}
- (NSString*) sha512 {
const char *s=[self cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData=[NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA512_DIGEST_LENGTH]={0};
CC_SHA512(keyData.bytes, (CC_LONG)keyData.length, digest);
NSData *out=[NSData dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
NSString *hash=[out description];
hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""];
return hash;
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
buildForArchiving = "YES">
<BuildableReference
BuildableIdentifier = 'primary'
BlueprintIdentifier = '7D82FE4863E609B26FEC5D4C'
BlueprintIdentifier = '519D6001C06A5C0A87E22E14'
BlueprintName = 'PNObject'
ReferencedContainer = 'container:Pods.xcodeproj'
BuildableName = 'PNObject.framework'>

22
Example/Pods/RZDataBinding/LICENSE generated Normal file
View File

@ -0,0 +1,22 @@
Copyright 2014 Raizlabs and other contributors
http://raizlabs.com/
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.

172
Example/Pods/RZDataBinding/README.md generated Normal file
View File

@ -0,0 +1,172 @@
# RZDataBinding
[![Version](https://img.shields.io/cocoapods/v/RZDataBinding.svg?style=flat)](http://cocoadocs.org/docsets/RZDataBinding)
<p align="center">
<img src="http://cl.ly/image/1r0I0x401W2m/chain.png"
alt="RZDataBinding">
</p>
## Overview
RZDataBinding is a framework designed to help maintain data integrity in your iOS or OS X app. It is built using the standard Key-Value Observation (KVO) framework, but is safer and provides additional functionality. Like KVO, RZDataBinding helps to avoid endless delegate chains by establishing direct callbacks for when an object changes state.
## Installation
Install using [CocoaPods](http://cocoapods.org) (recommended) by adding the following line to your Podfile:
`pod "RZDataBinding"`
Alternatively, download the repository and add the contents of the RZDataBinding directory to your project.
## Demo Project
An example project is available in the Example directory. You can quickly check it out with
`pod try RZDataBinding`
Or download the zip from github and run it manually.
<p align="center">
<img src="http://cl.ly/image/152x112l0i2n/rzdb.gif"
alt="RZDataBinding">
</p>
The demo shows a basic usage of RZDataBinding, but is by no means the canonical or most advanced use case.
##Usage
**Register a callback for when the keypath of an object changes:**
``` obj-c
// Register a selector to be called on a given target whenever keyPath changes on the receiver.
// Action must take either zero or exactly one parameter, an NSDictionary.
// If the method has a parameter, the dictionary will contain values for the appropriate
// RZDBChangeKeys. If keys are absent, they can be assumed to be nil. Values will not be NSNull.
- (void)rz_addTarget:(id)target
action:(SEL)action
forKeyPathChange:(NSString *)keyPath;
```
**Bind values of two objects together either directly or with a function:**
``` obj-c
// Binds the value of a given key of the receiver to the value of a key path of another object.
// When the key path of the object changes, the bound key of the receiver is also changed.
- (void)rz_bindKey:(NSString *)key
toKeyPath:(NSString *)foreignKeyPath
ofObject:(id)object;
// Same as the above method, but the binding function is first applied
// to the changed value before setting the value of the bound key.
// If nil, the identity function is assumed, making it identical to regular rz_bindKey.
- (void)rz_bindKey:(NSString *)key
toKeyPath:(NSString *)foreignKeyPath
ofObject:(id)object
withFunction:(RZDBKeyBindingFunction)bindingFunction;
```
Targets can be removed and keys unbound with corresponding removal methods, but unlike with standard KVO, you are not obligated to do so. RZDataBinding will automatically cleanup observers before objects are deallocated.
## Why not use plain KVO?
Consider the following code, which calls `nameChanged:` when a user object's name changes, and reload a collection view when the user's preferences change:
**Using KVO:**
``` obj-c
static void* const MyKVOContext = (void *)&MyKVOContext;
- (void)setupKVO
{
[self.user addObserver:self
forKeyPath:@"name"
options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
context:MyKVOContext];
[self.user addObserver:self
forKeyPath:@"preferences"
options:kNilOptions
context:MyKVOContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object change:(NSDictionary *)change
context:(void *)context
{
if ( context == MyKVOContext ) {
if ( [object isEqual:self.user] ) {
if ( [keyPath isEqualToString:@"name"] ) {
[self nameChanged:change];
}
else if ( [keyPath isEqualToString:@"preferences"] ) {
[self.collectionView reloadData];
}
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc
{
[self.user removeObserver:self forKeyPath:@"name" context:MyKVOContext];
[self.user removeObserver:self forKeyPath:@"preferences" context:MyKVOContext];
}
```
**Using RZDataBinding:**
``` obj-c
- (void)setupKVO
{
[self.user rz_addTarget:self
action:@selector(nameChanged:)
forKeyPathChange:@"name"];
[self.user rz_addTarget:self.collectionView
action:@selector(reloadData)
forKeyPathChange:@"preferences"];
}
```
Aside from the obvious reduction in code, the RZDataBinding implementation demonstrates several other wins:
1. No need to manage different KVO contexts and check which object/keypath changed
2. No need to implement an instance method, meaning *any* object can be added as a target
3. No need to teardown before deallocation (standard KVO crashes if you fail to do this)
## Safe Keypaths
RZDataBinding also provides [several convenience macros](RZDataBinding/RZDBMacros.h) to create type-safe keypaths. When running in `DEBUG` mode, invalid keypaths will generate a compiler error:
``` obj-c
// Creates the keypath @"text", ensuring it exists on objects of type UILabel
RZDB_KP(UILabel, text);
// Creates @"layer.cornerRadius", ensuring the keypath exists on myView
RZDB_KP_OBJ(myView, layer.cornerRadius);
// Creates @"session.user.name", ensuring the keypath exists on self
RZDB_KP_SELF(session.user.name);
```
You should *always* use these macros instead of literal strings, because of the additional type checks they provide. Note that in production these macros simplify to literal string generation to avoid any additional overhead.
## Callback Coalescing (Advanced)
RZDataBinding also provides a coalescing mechanism for fine-tuning areas of your application that receive or send a high number of KVO notifications, which may incur a performance cost. For example, a complex view might trigger an expensive layout operation whenever one of several properties changes. Or, some work may require changing properties several times before they settle to final values. In these cases, it may be beneficial to have RZDataBinding treat a block of work as an "atomic" event. That is, supported callbacks should be coalesced and sent once, when the work completes.
[`RZDBCoalesce`](RZDataBinding/RZDBCoalesce.h) provides a block interface:
``` obj-c
[RZDBCoalesce coalesceBlock:^{
// Callbacks within this block are coalesced,
// and sent only once, after the block completes
}];
```
Callbacks are not coalesced by default, even within an `RZDBCoalesce` event. The `rz_addTarget:action:` methods can opt in to support coalescing by specifying a coalesce proxy as the callback target:
``` obj-c
[object rz_addTarget:[self rz_coalesceProxy]
action:@selector(expensiveCallback)
forKeyPathChange:RZDB_KP_OBJ(object, key.path)];
```
In this example, the intended target is `self`, but if a coalesce event is in progress these messages will be coalesced and deferred until the event completes. Note that only `rz_addTarget:action:` callbacks may support coalescing; bindings established with the `rz_bindKey:` methods will never be coalesced.
## Author
Rob Visentin, rob.visentin@raizlabs.com
## License
RZDataBinding is available under the MIT license. See the LICENSE file for more info.

View File

@ -0,0 +1,192 @@
//
// NSObject+RZDataBinding.h
//
// Created by Rob Visentin on 9/17/14.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
//
#import "RZDBTransforms.h"
#pragma mark - Constants and Definitions
/**
* The value for this key is the object that changed. This key is always present.
*/
OBJC_EXTERN NSString* const kRZDBChangeKeyObject;
/**
* If present, the value for this key is the previous value on a key path change.
*/
OBJC_EXTERN NSString* const kRZDBChangeKeyOld;
/**
* If present, the value for this key is the new value on a key path change, or the exisiting value for the key path for the initial call.
*/
OBJC_EXTERN NSString* const kRZDBChangeKeyNew;
/**
* The value for this key is the key path that changed value. This key is always present.
*/
OBJC_EXTERN NSString* const kRZDBChangeKeyKeyPath;
/**
* Set this to 1 (recommended) to enable automatic cleanup of observers on object deallocation.
* If enabled, it is safe to observe or bind to weak references, and there is no need to call rz_removeTarget
* or rz_unbindKey before targets or observed objects are deallocated. To achieve automatic cleanup,
* RZDB swizzles the dealloc method to ensure observers are properly invalidated. There are other ways of implementing similar
* behavior, but this has been found to be both the safest and most reliable in production.
*
* If set to 0 (not recommended), objects MUST remove themselves as targets and unbind their keys from any observed objects before being deallocated.
* Failure to do so will result in crashes (just like standard KVO). Additionally, you should not add a target to or bind keys to
* objects without first establishing a strong reference. Otherwise, the foreign object might be deallocated before the observer, causing in a crash.
* If you choose to disable global automatic cleanup by setting this to 0, you must cleanup observers manually.
*
* @see rz_cleanupObservers
*/
#ifndef RZDB_AUTOMATIC_CLEANUP
#define RZDB_AUTOMATIC_CLEANUP 1
#endif
#pragma mark - NSObject+RZDataBinding interface
@interface NSObject (RZDataBinding)
/**
* Register a selector to be called on a given target whenever keyPath changes on the receiver. The selector is not called immediately.
*
* @param target The object on which to call the action selector. Must be non-nil. This object is not retained.
* @param action The selector to call on the target. Must not be NULL. The method must take either zero or exactly one parameter, an NSDictionary, and have a void return type. If the method has an NSDictionary parameter, the dictionary will contain values for the appropriate RZDBChangeKeys. If keys are absent, they can be assumed to be nil. Values will not be NSNull.
* @param keyPath The key path of the receiver for which changes should trigger an action. Must be KVC compliant.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath;
/**
* Register a selector to be called on a given target whenever keyPath changes on the receiver.
*
* @param target The object on which to call the action selector. Must be non-nil. This object is not retained.
* @param action The selector to call on the target. Must not be NULL. The method must take either zero or exactly one parameter, an NSDictionary, and have a void return type. If the method has an NSDictionary parameter, the dictionary will contain values for the appropriate RZDBChangeKeys. If keys are absent, they can be assumed to be nil. Values will not be NSNull.
* @param keyPath The key path of the receiver for which changes should trigger an action. Must be KVC compliant.
* @param callImmediately If YES, the action is also called immediately before this method returns. In this case the change dictionary, if present, will not contain a value for kRZDBChangeKeyOld.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath callImmediately:(BOOL)callImmediately;
/**
* A convenience method that calls rz_addTarget:action:forKeyPathChange: for each keyPath in the keyPaths array.
*
* @param target The object on which to call the action selector. Must be non-nil. This object is not retained.
* @param action The selector to call on the target. Must not be NULL. See rz_addTarget documentation for more details.
* @param keyPaths An array of key paths that should trigger an action. Each key path must be KVC compliant.
*
* @note The action is not called immediately.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChanges:(NSArray *)keyPaths;
/**
* A convenience method that calls rz_addTarget:action:forKeyPathChange: for each keyPath in the keyPaths array.
*
* @param target The object on which to call the action selector. Must be non-nil. This object is not retained.
* @param action The selector to call on the target. Must not be NULL. See rz_addTarget documentation for more details.
* @param keyPaths An array of key paths that should trigger an action. Each key path must be KVC compliant.
* @param callImmediately If YES, the action is also called immediately before this method returns. If the action takes no arguments, it will be called once. If the action takes a change dictonary parameter, it will be called once for each keypath, with the appropriate change dict. Note that in this case the dictionary will not contain a value for kRZDBChangeKeyOld.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChanges:(NSArray *)keyPaths callImmediately:(BOOL)callImmediately;
/**
* Removes previously registered target/action pairs so that the actions are no longer called when the receiver changes value for keyPath.
*
* @param target The target to remove. Must be non-nil.
* @param action The action to remove. Pass NULL to remove all actions registered for the target.
* @param keyPath The key path to remove the target/action pair for.
*
* @note If RZDB_AUTOMATIC_CLEANUP is enabled, then there is obligation to call this method before either the target or receiver are deallocated.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_removeTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath;
/**
* Binds the value of a given key of the receiver to the value of a key path of another object. When the key path of the object changes, the bound key of the receiver is set to the same value. The receiver's value for the key will match the value for the object's foreign key path before this method returns.
*
* @param key The receiver's key whose value should be bound to the value of a foreign key path. Must be KVC compliant.
* @param foreignKeyPath A key path of another object to which the receiver's key value should be bound. Must be KVC compliant.
* @param object An object with a key path that the receiver should bind to.
*
* @note If binding a primitive-type key to a keypath that may hit a nil object, you MUST use
* rz_bindKey:toKeyPath:ofObject:withTransform: instead. This is because attempting to set a nil
* value to a primitive-type using KVC causes a crash. In this case it may be helpful to use
* one of the default RZDBTransforms.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_bindKey:(NSString *)key toKeyPath:(NSString *)foreignKeyPath ofObject:(id)object;
/**
* Binds the value of a given key of the receiver to the value of a key path of another object. When the key path of the object changes, the binding transform is invoked and the bound key of the receiver is set to the transform's return value. The receiver's value for the key will be set before this method returns.
*
* @param key The receiver's key whose value should be bound to the value of a foreign key path. Must be KVC compliant.
* @param foreignKeyPath A key path of another object to which the receiver's key value should be bound. Must be KVC compliant.
* @param object An object with a key path that the receiver should bind to.
* @param bindingTransform The transform to apply to changed values before setting the value of the bound key. If nil, the identity transform is assumed, making this method identical to regular rz_bindKey:.
* You may use the constant RZDBTransforms provided for convenience.
*
* @see RZDB_KP macro for creating keypaths, and RZDBTransforms for constant transforms.
*/
- (void)rz_bindKey:(NSString *)key toKeyPath:(NSString *)foreignKeyPath ofObject:(id)object withTransform:(RZDBKeyBindingTransform)bindingTransform;
/**
* Unbinds the given key of the receiver from the key path of another object.
*
* @param key The key to unbind.
* @param foreignKeyPath The key path that the key should be unbound from.
* @param object The object that the receiver should be unbound from.
*
* @note If RZDB_AUTOMATIC_CLEANUP is enabled, then there is no obligation to call this method before either the receiver or the foreign object are deallocated.
*
* @see RZDB_KP macro for creating keypaths.
*/
- (void)rz_unbindKey:(NSString *)key fromKeyPath:(NSString *)foreignKeyPath ofObject:(id)object;
#if !RZDB_AUTOMATIC_CLEANUP
/**
* Removes all callbacks and bindings both to and from the receiver.
* This method essentially resets the receiver to a pristine state with respect to RZDataBinding.
*
* If RZDB_AUTOMATIC_CLEANUP is not enabled, you MUST call this method on any
* observing or observed object it is deallocated. Failure to do so will result in a crash (just like standard KVO).
*
* @note This method breaks all bindings and callbacks on the receiver, including those created
* by other clients. Therefore it is only safe to call this method from the receiver's dealloc method.
*/
- (void)rz_cleanupObservers;
#endif
@end

View File

@ -0,0 +1,515 @@
//
// NSObject+RZDataBinding.m
//
// Created by Rob Visentin on 9/17/14.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
//
#import <objc/runtime.h>
#import <objc/message.h>
#import "NSObject+RZDataBinding.h"
#import "RZDBMacros.h"
@class RZDBObserver;
@class RZDBObserverContainer;
// public change keys
NSString* const kRZDBChangeKeyObject = @"RZDBChangeObject";
NSString* const kRZDBChangeKeyOld = @"RZDBChangeOld";
NSString* const kRZDBChangeKeyNew = @"RZDBChangeNew";
NSString* const kRZDBChangeKeyKeyPath = @"RZDBChangeKeyPath";
// private change keys
static NSString* const kRZDBChangeKeyBoundKey = @"_RZDBChangeBoundKey";
static NSString* const kRZDBChangeKeyBindingTransformKey = @"_RZDBChangeBindingTransform";
static void* const kRZDBSwizzledDeallocKey = (void *)&kRZDBSwizzledDeallocKey;
static void* const kRZDBKVOContext = (void *)&kRZDBKVOContext;
#define RZDBNotNull(obj) ((obj) != nil && ![(obj) isEqual:[NSNull null]])
#pragma mark - RZDataBinding_Private interface
// methods used to implement RZDB_AUTOMATIC_CLEANUP
BOOL rz_requiresDeallocSwizzle(Class class);
void rz_swizzleDeallocIfNeeded(Class class);
@interface NSObject (RZDataBinding_Private)
- (NSMutableArray *)rz_registeredObservers;
- (void)rz_setRegisteredObservers:(NSMutableArray *)registeredObservers;
- (RZDBObserverContainer *)rz_dependentObservers;
- (void)rz_setDependentObservers:(RZDBObserverContainer *)dependentObservers;
- (void)rz_addTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey bindingTransform:(RZDBKeyBindingTransform)bindingTransform forKeyPath:(NSString *)keyPath withOptions:(NSKeyValueObservingOptions)options;
- (void)rz_removeTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey forKeyPath:(NSString *)keyPath;
- (void)rz_observeBoundKeyChange:(NSDictionary *)change;
- (void)rz_setBoundKey:(NSString *)key withValue:(id)value transform:(RZDBKeyBindingTransform)transform;
@end
#pragma mark - RZDBObserver interface
@interface RZDBObserver : NSObject;
@property (assign, nonatomic) __unsafe_unretained NSObject *observedObject;
@property (copy, nonatomic) NSString *keyPath;
@property (copy, nonatomic) NSString *boundKey;
@property (assign, nonatomic) NSKeyValueObservingOptions observationOptions;
@property (assign, nonatomic) __unsafe_unretained id target;
@property (assign, nonatomic) SEL action;
@property (strong, nonatomic) NSMethodSignature *methodSignature;
@property (copy, nonatomic) RZDBKeyBindingTransform bindingTransform;
- (instancetype)initWithObservedObject:(NSObject *)observedObject keyPath:(NSString *)keyPath observationOptions:(NSKeyValueObservingOptions)observingOptions;
- (void)setTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey bindingTransform:(RZDBKeyBindingTransform)bindingTransform;
- (void)invalidate;
@end
#pragma mark - RZDBObserverContainer interface
@interface RZDBObserverContainer : NSObject
@property (strong, nonatomic) NSHashTable *observers;
- (void)addObserver:(RZDBObserver *)observer;
- (void)removeObserver:(RZDBObserver *)observer;
@end
#pragma mark - RZDataBinding implementation
@implementation NSObject (RZDataBinding)
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath
{
[self rz_addTarget:target action:action forKeyPathChange:keyPath callImmediately:NO];
}
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath callImmediately:(BOOL)callImmediately
{
NSParameterAssert(target);
NSParameterAssert(action);
NSKeyValueObservingOptions observationOptions = kNilOptions;
if ( [target methodSignatureForSelector:action].numberOfArguments > 2 ) {
observationOptions |= NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
}
if ( callImmediately ) {
observationOptions |= NSKeyValueObservingOptionInitial;
}
[self rz_addTarget:target action:action boundKey:nil bindingTransform:nil forKeyPath:keyPath withOptions:observationOptions];
}
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChanges:(NSArray *)keyPaths
{
[self rz_addTarget:target action:action forKeyPathChanges:keyPaths callImmediately:NO];
}
- (void)rz_addTarget:(id)target action:(SEL)action forKeyPathChanges:(NSArray *)keyPaths callImmediately:(BOOL)callImmediately
{
BOOL callMultiple = NO;
if ( callImmediately ) {
callMultiple = [target methodSignatureForSelector:action].numberOfArguments > 2;
}
[keyPaths enumerateObjectsUsingBlock:^(NSString *keyPath, NSUInteger idx, BOOL *stop) {
[self rz_addTarget:target action:action forKeyPathChange:keyPath callImmediately:callMultiple];
}];
if ( callImmediately && !callMultiple ) {
((void(*)(id, SEL))objc_msgSend)(target, action);
}
}
- (void)rz_removeTarget:(id)target action:(SEL)action forKeyPathChange:(NSString *)keyPath
{
[self rz_removeTarget:target action:action boundKey:nil forKeyPath:keyPath];
}
- (void)rz_bindKey:(NSString *)key toKeyPath:(NSString *)foreignKeyPath ofObject:(id)object
{
[self rz_bindKey:key toKeyPath:foreignKeyPath ofObject:object withTransform:nil];
}
- (void)rz_bindKey:(NSString *)key toKeyPath:(NSString *)foreignKeyPath ofObject:(id)object withTransform:(RZDBKeyBindingTransform)bindingTransform
{
NSParameterAssert(key);
NSParameterAssert(foreignKeyPath);
if ( object != nil ) {
@try {
id val = [object valueForKeyPath:foreignKeyPath];
[self rz_setBoundKey:key withValue:val transform:bindingTransform];
}
@catch (NSException *exception) {
[NSException raise:NSInvalidArgumentException format:@"RZDataBinding cannot bind key:%@ to key path:%@ of object:%@. Reason: %@", key, foreignKeyPath, [object description], exception.reason];
}
[object rz_addTarget:self action:@selector(rz_observeBoundKeyChange:) boundKey:key bindingTransform:bindingTransform forKeyPath:foreignKeyPath withOptions:NSKeyValueObservingOptionNew];
}
}
- (void)rz_unbindKey:(NSString *)key fromKeyPath:(NSString *)foreignKeyPath ofObject:(id)object
{
[object rz_removeTarget:self action:@selector(rz_observeBoundKeyChange:) boundKey:key forKeyPath:foreignKeyPath];
}
@end
#pragma mark - RZDataBinding_Private implementation
@implementation NSObject (RZDataBinding_Private)
- (NSMutableArray *)rz_registeredObservers
{
return objc_getAssociatedObject(self, @selector(rz_registeredObservers));
}
- (void)rz_setRegisteredObservers:(NSMutableArray *)registeredObservers
{
objc_setAssociatedObject(self, @selector(rz_registeredObservers), registeredObservers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (RZDBObserverContainer *)rz_dependentObservers
{
return objc_getAssociatedObject(self, @selector(rz_dependentObservers));
}
- (void)rz_setDependentObservers:(RZDBObserverContainer *)dependentObservers
{
objc_setAssociatedObject(self, @selector(rz_dependentObservers), dependentObservers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)rz_addTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey bindingTransform:(RZDBKeyBindingTransform)bindingTransform forKeyPath:(NSString *)keyPath withOptions:(NSKeyValueObservingOptions)options
{
NSMutableArray *registeredObservers = nil;
RZDBObserverContainer *dependentObservers = nil;
RZDBObserver *observer = [[RZDBObserver alloc] initWithObservedObject:self keyPath:keyPath observationOptions:options];
[observer setTarget:target action:action boundKey:boundKey bindingTransform:bindingTransform];
@synchronized (self) {
registeredObservers = [self rz_registeredObservers];
if ( registeredObservers == nil ) {
registeredObservers = [NSMutableArray array];
[self rz_setRegisteredObservers:registeredObservers];
}
[registeredObservers addObject:observer];
}
@synchronized (target) {
dependentObservers = [target rz_dependentObservers];
if ( dependentObservers == nil ) {
dependentObservers = [[RZDBObserverContainer alloc] init];
[target rz_setDependentObservers:dependentObservers];
}
[dependentObservers addObserver:observer];
}
#if RZDB_AUTOMATIC_CLEANUP
rz_swizzleDeallocIfNeeded([self class]);
rz_swizzleDeallocIfNeeded([target class]);
#endif
}
- (void)rz_removeTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey forKeyPath:(NSString *)keyPath
{
@synchronized (self) {
NSMutableArray *registeredObservers = [self rz_registeredObservers];
[registeredObservers enumerateObjectsUsingBlock:^(RZDBObserver *observer, NSUInteger idx, BOOL *stop) {
BOOL targetsEqual = (target == observer.target);
BOOL actionsEqual = (action == NULL || action == observer.action);
BOOL boundKeysEqual = (boundKey == observer.boundKey || [boundKey isEqualToString:observer.boundKey]);
BOOL keyPathsEqual = [keyPath isEqualToString:observer.keyPath];
BOOL allEqual = (targetsEqual && actionsEqual && boundKeysEqual && keyPathsEqual);
if ( allEqual ) {
[observer invalidate];
}
}];
}
}
- (void)rz_observeBoundKeyChange:(NSDictionary *)change
{
NSString *boundKey = change[kRZDBChangeKeyBoundKey];
if ( boundKey != nil ) {
id value = change[kRZDBChangeKeyNew];
[self rz_setBoundKey:boundKey withValue:value transform:change[kRZDBChangeKeyBindingTransformKey]];
}
}
- (void)rz_setBoundKey:(NSString *)key withValue:(id)value transform:(RZDBKeyBindingTransform)transform
{
id currentValue = [self valueForKey:key];
if ( transform != nil ) {
value = transform(value);
}
if ( currentValue != value && ![currentValue isEqual:value] ) {
[self setValue:value forKey:key];
}
}
- (void)rz_cleanupObservers
{
NSMutableArray *registeredObservers = [self rz_registeredObservers];
RZDBObserverContainer *dependentObservers = [self rz_dependentObservers];
[[registeredObservers copy] enumerateObjectsUsingBlock:^(RZDBObserver *obs, NSUInteger idx, BOOL *stop) {
[obs invalidate];
}];
[[dependentObservers.observers allObjects] enumerateObjectsUsingBlock:^(RZDBObserver *obs, NSUInteger idx, BOOL *stop) {
[obs invalidate];
}];
}
@end
#pragma mark - RZDBObserver implementation
@implementation RZDBObserver
- (instancetype)initWithObservedObject:(NSObject *)observedObject keyPath:(NSString *)keyPath observationOptions:(NSKeyValueObservingOptions)observingOptions
{
self = [super init];
if ( self != nil ) {
_observedObject = observedObject;
_keyPath = keyPath;
_observationOptions = observingOptions;
}
return self;
}
- (void)setTarget:(id)target action:(SEL)action boundKey:(NSString *)boundKey bindingTransform:(RZDBKeyBindingTransform)bindingTransform
{
self.target = target;
self.action = action;
self.methodSignature = [target methodSignatureForSelector:action];
self.boundKey = boundKey;
self.bindingTransform = bindingTransform;
[self.observedObject addObserver:self forKeyPath:self.keyPath options:self.observationOptions context:kRZDBKVOContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ( context == kRZDBKVOContext ) {
if ( self.methodSignature.numberOfArguments > 2 ) {
NSDictionary *changeDict = [self changeDictForKVOChange:change];
((void(*)(id, SEL, NSDictionary *))objc_msgSend)(self.target, self.action, changeDict);
}
else {
((void(*)(id, SEL))objc_msgSend)(self.target, self.action);
}
}
}
- (NSDictionary *)changeDictForKVOChange:(NSDictionary *)kvoChange
{
NSMutableDictionary *changeDict = [NSMutableDictionary dictionary];
if ( self.observedObject != nil ) {
changeDict[kRZDBChangeKeyObject] = self.observedObject;
}
if ( RZDBNotNull(kvoChange[NSKeyValueChangeOldKey]) ) {
changeDict[kRZDBChangeKeyOld] = kvoChange[NSKeyValueChangeOldKey];
}
if ( RZDBNotNull(kvoChange[NSKeyValueChangeNewKey]) ) {
changeDict[kRZDBChangeKeyNew] = kvoChange[NSKeyValueChangeNewKey];
}
if ( self.keyPath != nil ) {
changeDict[kRZDBChangeKeyKeyPath] = self.keyPath;
}
if ( self.boundKey != nil ) {
changeDict[kRZDBChangeKeyBoundKey] = self.boundKey;
}
if ( self.bindingTransform != nil ) {
changeDict[kRZDBChangeKeyBindingTransformKey] = self.bindingTransform;
}
return [changeDict copy];
}
- (void)invalidate
{
[[self.target rz_dependentObservers] removeObserver:self];
[[self.observedObject rz_registeredObservers] removeObject:self];
// KVO throws an exception when removing an observer that was never added.
// This should never be a problem given how things are setup, but make sure to avoid a crash.
@try {
[self.observedObject removeObserver:self forKeyPath:self.keyPath context:kRZDBKVOContext];
}
@catch (__unused NSException *exception) {
RZDBLog(@"RZDataBinding attempted to remove an observer from object:%@, but the observer was never added. This shouldn't have happened, but won't affect anything going forward.", self.observedObject);
}
self.observedObject = nil;
self.target = nil;
self.action = NULL;
self.methodSignature = nil;
}
@end
#pragma mark - RZDBObserverContainer implementation
@implementation RZDBObserverContainer
- (instancetype)init
{
self = [super init];
if ( self != nil ) {
_observers = [NSHashTable weakObjectsHashTable];
}
return self;
}
- (void)addObserver:(RZDBObserver *)observer
{
@synchronized (self) {
[self.observers addObject:observer];
}
}
- (void)removeObserver:(RZDBObserver *)observer
{
@synchronized (self) {
[self.observers removeObject:observer];
}
}
@end
// a class doesn't need dealloc swizzled if it or a superclass has been swizzled already
BOOL rz_requiresDeallocSwizzle(Class class)
{
BOOL swizzled = NO;
for ( Class currentClass = class; !swizzled && currentClass != nil; currentClass = class_getSuperclass(currentClass) ) {
swizzled = [objc_getAssociatedObject(currentClass, kRZDBSwizzledDeallocKey) boolValue];
}
return !swizzled;
}
// In order for automatic cleanup to work, observers must be removed before deallocation.
// This method ensures that rz_cleanupObservers is called in the dealloc of classes of objects
// that are used in RZDataBinding.
void rz_swizzleDeallocIfNeeded(Class class)
{
static SEL deallocSEL = NULL;
static SEL cleanupSEL = NULL;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
deallocSEL = sel_getUid("dealloc");
cleanupSEL = sel_getUid("rz_cleanupObservers");
});
@synchronized (class) {
if ( !rz_requiresDeallocSwizzle(class) ) {
// dealloc swizzling already resolved
return;
}
objc_setAssociatedObject(class, kRZDBSwizzledDeallocKey, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
Method dealloc = NULL;
// search instance methods of the class (does not search superclass methods)
unsigned int n;
Method *methods = class_copyMethodList(class, &n);
for ( unsigned int i = 0; i < n; i++ ) {
if ( method_getName(methods[i]) == deallocSEL ) {
dealloc = methods[i];
break;
}
}
free(methods);
if ( dealloc == NULL ) {
Class superclass = class_getSuperclass(class);
// class does not implement dealloc, so implement it directly
class_addMethod(class, deallocSEL, imp_implementationWithBlock(^(__unsafe_unretained id self) {
// cleanup RZDB observers
((void(*)(id, SEL))objc_msgSend)(self, cleanupSEL);
// ARC automatically calls super when dealloc is implemented in code,
// but when provided our own dealloc IMP we have to call through to super manually
struct objc_super superStruct = (struct objc_super){ self, superclass };
((void (*)(struct objc_super*, SEL))objc_msgSendSuper)(&superStruct, deallocSEL);
}), method_getTypeEncoding(dealloc));
}
else {
// class implements dealloc, so extend the existing implementation
__block IMP deallocIMP = method_setImplementation(dealloc, imp_implementationWithBlock(^(__unsafe_unretained id self) {
// cleanup RZDB observers
((void(*)(id, SEL))objc_msgSend)(self, cleanupSEL);
// invoke the original dealloc IMP
((void(*)(id, SEL))deallocIMP)(self, deallocSEL);
}));
}
}

View File

@ -0,0 +1,111 @@
//
// RZDBCoalesce.h
//
// Created by Rob Visentin on 4/1/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
//
#import <Foundation/Foundation.h>
#pragma mark - NSObject+RZDBCoalesce interface
/**
* Provides an interface for supporting coalesced data binding callbacks.
*/
@interface NSObject (RZDBCoalesce)
/**
* Returns a proxy object that will participate in coalescing events.
*
* Use [target rz_coalesceProxy] as the target of the rz_addTarget:action: methods to support
* coalescing for a target/action pair. If the callback occurs during a an RZDBCoalesce event, it will be
* coalesced and deferred until the end RZDBCoalesce is committed.
*
* @note You should generally not call methods on the coalesce proxy directly.
* The proxy will treat any 0-arg or 1-dictionary-arg methods with void return type as RZDB callbacks,
* and coalesce them accordingly.
*
* @see RZDBCoalesce for how to begin/end coalesce events.
*
* @return A proxy object to use as a data binding target in the rz_addTarget:action: methods.
*/
- (id)rz_coalesceProxy;
@end
#pragma mark - RZDBCoalesce interface
/**
* There may be chunks of work that should be completed "atomically" with respect to RZDataBinding.
* That is, actions registered using the rz_addTarget:action: methods that support coalescing
* will be fired once, when the work is completed.
*
* The RZDBCoalesce object provides class methods to manage coalescing events.
*
* Coalescing is an advanced feature that should generally only be used if you encounter a performance issue,
* or find some other requirement for it.
*
* @see NSObject+RZDBCoalesce for how to support coalesced callbacks.
*/
@interface RZDBCoalesce : NSObject
/**
* Begin coalescing events for the current thread.
* Changes that occur during the coalesce that would trigger actions registered to coalesce proxies with
* the rz_addTarget:action: methods are instead coalesced and executed once when the coalesce ends.
*
* Every call to +begin MUST be balanced by a call to +commit on the same thread.
* It is fine to begin a coalesce while already coalescing--
* the coalesce will simply not end until both matching commits are hit.
*
* @note Bindings that occur during a coalesce still occur immediately.
*
* @see NSObject+RZDBCoalesce for how to support coalesced callbacks.
*/
+ (void)begin;
/**
* Commit the current coalesce, sending the coalesced change callbacks.
* If this commit closes a nested coalesce, callbacks are not sent until the outermost coalesce is committed.
*
* Calling this method from outside a coalesce has no effect.
*/
+ (void)commit;
/**
* Convenience method that first calls +begin, then executes the block, then calls +commit.
* You should prefer this method where possible to avoid programmer error (i.e. forgetting to call +commit).
*
* @param coalesceBlock The block to execute inside a coalesce. Must be non-nil.
*
* @see NSObject+RZDBCoalesce for how to support coalesced callbacks.
*/
+ (void)coalesceBlock:(void (^)())coalesceBlock;
/**
* Cannot instantiate RZDBCoalesce directly. Use the class methods instead.
*/
- (instancetype)init __attribute__((unavailable("Cannot instantiate RZDBCoalesce directly. Use the class methods instead.")));
@end

View File

@ -0,0 +1,297 @@
//
// RZDBCoalesce.m
//
// Created by Rob Visentin on 4/1/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
//
#import <objc/runtime.h>
#import <objc/message.h>
#import "RZDBCoalesce.h"
#import "NSObject+RZDataBinding.h"
static NSString* const kRZDBCoalesceStorageKey = @"RZDBCoalesce";
#pragma mark - RZDBNotification interface
@interface RZDBNotification : NSObject
@property (weak, nonatomic) id target;
@property (assign, nonatomic) SEL action;
@property (strong, nonatomic) NSMutableDictionary *changeDict;
+ (instancetype)notificationWithInvocation:(NSInvocation *)invocation;
- (void)send;
@end
#pragma mark - RZDBCoalesceProxy interface
@interface RZDBCoalesceProxy : NSProxy
@property (assign, nonatomic) __unsafe_unretained id representedObject;
+ (instancetype)proxyForObject:(id)object;
@end
#pragma mark - RZDBCoalesce private interface
@interface RZDBCoalesce ()
@property (assign, nonatomic) NSInteger beginCount;
@property (strong, nonatomic, readonly) NSMutableArray *notifications;
@end
#pragma mark - RZDBCoalesce implementation
@implementation RZDBCoalesce
+ (void)begin
{
RZDBCoalesce *current = [self currentCoalesce];
if ( current == nil ) {
[self setCurrentCoalesce:[[self alloc] init]];
}
else {
current.beginCount++;
}
}
+ (void)commit
{
RZDBCoalesce *current = [self currentCoalesce];
current.beginCount--;
if ( current.beginCount == 0 ) {
[self setCurrentCoalesce:nil];
[current.notifications enumerateObjectsUsingBlock:^(RZDBNotification *notification, NSUInteger idx, BOOL *stop) {
[notification send];
}];
}
}
+ (void)coalesceBlock:(void (^)())coalesceBlock
{
NSParameterAssert(coalesceBlock);
[RZDBCoalesce begin];
coalesceBlock();
[RZDBCoalesce commit];
}
#pragma mark - private methods
+ (RZDBCoalesce *)currentCoalesce
{
return [NSThread currentThread].threadDictionary[kRZDBCoalesceStorageKey];
}
+ (void)setCurrentCoalesce:(RZDBCoalesce *)current
{
if ( current != nil ) {
[NSThread currentThread].threadDictionary[kRZDBCoalesceStorageKey] = current;
}
else {
[[NSThread currentThread].threadDictionary removeObjectForKey:kRZDBCoalesceStorageKey];
}
}
- (instancetype)init
{
self = [super init];
if ( self ) {
_beginCount = 1;
_notifications = [NSMutableArray array];
}
return self;
}
- (void)addNotification:(RZDBNotification *)notification
{
NSUInteger existingIdx = [self.notifications indexOfObjectPassingTest:^BOOL(RZDBNotification *existing, NSUInteger idx, BOOL *stop) {
return [notification isEqual:existing];
}];
if ( existingIdx != NSNotFound ) {
RZDBNotification *existing = self.notifications[existingIdx];
if ( notification.changeDict[kRZDBChangeKeyNew] != nil ) {
existing.changeDict[kRZDBChangeKeyNew] = notification.changeDict[kRZDBChangeKeyNew];
}
else {
[existing.changeDict removeObjectForKey:kRZDBChangeKeyNew];
}
}
else {
[self.notifications addObject:notification];
}
}
@end
#pragma mark - RZDBNotification implementation
@implementation RZDBNotification
+ (instancetype)notificationWithInvocation:(NSInvocation *)invocation
{
RZDBNotification *notification = nil;
NSMethodSignature *methodSig = invocation.methodSignature;
// rzdb callbacks must have void return type, and
// if there are any arguments, the first and only argument must be a dictionary
if ( methodSig.methodReturnLength == 0 && (methodSig.numberOfArguments == 2 || methodSig.numberOfArguments == 3) ) {
notification = [[self alloc] init];
notification.target = invocation.target;
notification.action = invocation.selector;
if ( methodSig.numberOfArguments == 3 && strcmp([methodSig getArgumentTypeAtIndex:2], @encode(id)) == 0 ) {
__unsafe_unretained id arg1;
[invocation getArgument:&arg1 atIndex:2];
if ( [arg1 isKindOfClass:[NSDictionary class]] ) {
notification.changeDict = [arg1 mutableCopy];
}
else {
notification = nil;
}
}
}
return notification;
}
- (BOOL)isEqual:(id)object
{
BOOL equal = [super isEqual:object];
if ( !equal && [object isKindOfClass:[RZDBNotification class]] ) {
RZDBNotification *other = (RZDBNotification *)object;
equal = (self.target == other.target) &&
(self.action == other.action) &&
(self.changeDict == other.changeDict ||
(self.changeDict[kRZDBChangeKeyObject] == other.changeDict[kRZDBChangeKeyObject] &&
[self.changeDict[kRZDBChangeKeyKeyPath] isEqualToString:other.changeDict[kRZDBChangeKeyKeyPath]]
)
);
}
return equal;
}
- (void)send
{
if ( self.target != nil && self.action != NULL ) {
if ( self.changeDict != nil ) {
((void(*)(id, SEL, NSDictionary *))objc_msgSend)(self.target, self.action, [self.changeDict copy]);
}
else {
((void(*)(id, SEL))objc_msgSend)(self.target, self.action);
}
}
}
@end
#pragma mark - NSObject+RZDBCoalesce implementation
@implementation NSObject (RZDBCoalesce)
- (id)rz_coalesceProxy
{
@synchronized (self) {
id proxy = objc_getAssociatedObject(self, _cmd);
if ( proxy == nil ) {
proxy = [RZDBCoalesceProxy proxyForObject:self];
objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return proxy;
}
}
@end
#pragma mark - RZDBCoalesceProxy implementation
@implementation RZDBCoalesceProxy
+ (instancetype)proxyForObject:(id)object
{
RZDBCoalesceProxy *proxy = [self alloc];
proxy.representedObject = object;
return proxy;
}
- (Class)class
{
return [self.representedObject class];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
return [self.representedObject methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
invocation.target = self.representedObject;
RZDBCoalesce *currentCoalesce = [RZDBCoalesce currentCoalesce];
if ( currentCoalesce != nil ) {
// notificaton will be non-nil for a valid RZDataBinding callback
RZDBNotification *notification = [RZDBNotification notificationWithInvocation:invocation];
if ( notification != nil ) {
[currentCoalesce addNotification:notification];
}
else {
[invocation invoke];
}
}
else {
[invocation invoke];
}
}
- (void)doesNotRecognizeSelector:(SEL)aSelector
{
[self.representedObject doesNotRecognizeSelector:aSelector];
}
@end

View File

@ -0,0 +1,103 @@
//
// RZDBMacros.h
//
// Created by Rob Visentin on 3/18/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
#ifndef __RZDBMacros__
#define __RZDBMacros__
////////////////////////////////////////
//// ////
//// Logging ////
//// ////
////////////////////////////////////////
/**
* The method that should be used to log errors in RZDataBinding that are non-fatal,
* but may be useful in debugging. You might choose for example to `#define RZDBLog DDLogInfo`.
* The method defined must take exactly two parameters, a format string, and a variable list of arguments.
* By default, log messages are sent using NSLog.
*/
#ifndef RZDBLog
#define RZDBLog NSLog
#endif
////////////////////////////////////////
//// ////
//// Key Path creation Macros ////
//// ////
////////////////////////////////////////
/**
* Convenience macros for creating keypaths. An invalid keypath will throw a compile-time error when compiling in debug mode.
*
* The first parameter of these macros is used only for compile-time validation of the keypath.
*
* @return An NSString containing the keypath.
*
* @example RZDB_KP(NSObject, description.length) -> @"description.length"
* RZDB_KP_OBJ(MyLabel, text) -> @"text"
* RZDB_KP_SELF(user.firstName) -> @"user.firstName"
*/
#if DEBUG
#define RZDB_KP(Classname, keypath) ({\
Classname *_rzdb_keypath_obj; \
__unused __typeof(_rzdb_keypath_obj.keypath) _rzdb_keypath_prop; \
@#keypath; \
})
#define RZDB_KP_OBJ(object, keypath) ({\
__typeof(object) _rzdb_keypath_obj; \
__unused __typeof(_rzdb_keypath_obj.keypath) _rzdb_keypath_prop; \
@#keypath; \
})
#define RZDB_KP_PROTOCOL(ProtocolName, keypath) ({\
id<ProtocolName> _rzdb_keypath_obj; \
__unused __typeof(_rzdb_keypath_obj.keypath) _rzdb_keypath_prop; \
@#keypath; \
})
#else
#define RZDB_KP(Classname, keypath) (@#keypath)
#define RZDB_KP_OBJ(self, keypath) (@#keypath)
#define RZDB_KP_PROTOCOL(ProtocolName, keypath) (@#keypath)
#endif
/**
* @note This macro will implicitly retain self from within blocks while running in debug mode.
* The safe way to generate a keypath on self from within a block
* is to define a weak reference to self outside the block, and then use RZDB_KP_OBJ(weakSelf, keypath).
*/
#define RZDB_KP_SELF(keypath) RZDB_KP_OBJ(self, keypath)
/**
* Concatenate two keypath strings.
*
* keypath1 and keypath2 must be NSStrings like, for example, the ones created by the other RZDB keypath generation macros.
* The result is another NSString concatenating the two keypaths, but there is no implicit check that the key path exists.
*/
#define RZDB_KP_CONCAT(keypath1, keypath2) [keypath1 stringByAppendingFormat:@".%@", keypath2]
#endif /** __RZDBMacros__ defined */

View File

@ -0,0 +1,81 @@
//
// RZDataBinding.h
//
// Created by Rob Visentin on 4/7/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
#import <Foundation/Foundation.h>
#pragma mark - Definitions
/**
* A transform that takes a value as a parameter and returns an object.
*
* @param value The value that just changed on a foreign object for a bound key path.
*
* @return The value to set for the bound key. Ideally the returned value should depend solely on the input value.
*/
typedef id (^RZDBKeyBindingTransform)(id value);
#pragma mark - Convenience Constants
/**
* If value is nil, returns @(0), otherwise returns value.
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBNilToZeroTransform;
/**
* If value is nil, returns @(1), otherwise returns value.
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBNilToOneTransform;
/**
* If value is nil, returns NSValue with CGSizeZero, otherwise returns value.
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBNilToCGSizeZeroTransform;
/**
* If value is nil, returns NSValue with CGRectZero, otherwise returns value.
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBNilToCGRectZeroTransform;
/**
* If value is nil, returns NSValue with CGRectNull, otherwise returns value.
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBNilToCGRectNullTransform;
/**
* Returns @(![value boolValue])
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBLogicalNegateTransform;
/**
* Returns @(1.0 - [value doubleValue])
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBOneMinusTransform;
/**
* Returns @(~[value longLongValue])
*/
OBJC_EXTERN RZDBKeyBindingTransform const kRZDBBitwiseComplementTransform;

View File

@ -0,0 +1,71 @@
//
// RZDataBinding.m
//
// Created by Rob Visentin on 4/7/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
#import <CoreGraphics/CGGeometry.h>
#import "RZDBTransforms.h"
RZDBKeyBindingTransform const kRZDBNilToZeroTransform = ^(id value) {
return (value == nil) ? @(0) : value;
};
RZDBKeyBindingTransform const kRZDBNilToOneTransform = ^(id value) {
return (value == nil) ? @(1) : value;
};
RZDBKeyBindingTransform const kRZDBNilToCGSizeZeroTransform = ^(id value) {
if ( value == nil ) {
value = [NSValue valueWithBytes:&CGSizeZero objCType:@encode(CGSize)];
}
return value;
};
RZDBKeyBindingTransform const kRZDBNilToCGRectZeroTransform = ^(id value) {
if ( value == nil ) {
value = [NSValue valueWithBytes:&CGRectZero objCType:@encode(CGRect)];
}
return value;
};
RZDBKeyBindingTransform const kRZDBNilToCGRectNullTransform = ^(id value) {
if ( value == nil ) {
value = [NSValue valueWithBytes:&CGRectNull objCType:@encode(CGRect)];
}
return value;
};
RZDBKeyBindingTransform const kRZDBLogicalNegateTransform = ^(id value) {
return @(![value boolValue]);
};
RZDBKeyBindingTransform const kRZDBOneMinusTransform = ^(id value) {
return @(1.0 - [value doubleValue]);
};
RZDBKeyBindingTransform const kRZDBBitwiseComplementTransform = ^(id value) {
return @(~[value longLongValue]);
};

View File

@ -0,0 +1,31 @@
//
// RZDataBinding.h
//
// Created by Rob Visentin on 4/7/15.
// Copyright 2014 Raizlabs and other contributors
// http://raizlabs.com/
//
// 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.
#import "RZDBMacros.h"
#import "RZDBTransforms.h"
#import "RZDBCoalesce.h"
#import "NSObject+RZDataBinding.h"

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.4</string>
<string>1.0.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.5.6</string>
<string>0.5.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -333,6 +333,32 @@ The above copyright notice and this permission notice shall be included in all c
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.
## RZDataBinding
Copyright 2014 Raizlabs and other contributors
http://raizlabs.com/
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.
## StrongestPasswordValidator
Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>

View File

@ -404,6 +404,36 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>
Copyright 2014 Raizlabs and other contributors
http://raizlabs.com/
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.
</string>
<key>Title</key>
<string>RZDataBinding</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2016 Giuseppe Nucifora &lt;me@giuseppenucifora.com&gt;

View File

@ -100,6 +100,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "Pods-PNObject_Example/PEAR_FileManager_iOS.framework"
install_framework "Pods-PNObject_Example/PNObject.framework"
install_framework "Pods-PNObject_Example/PureLayout.framework"
install_framework "Pods-PNObject_Example/RZDataBinding.framework"
install_framework "Pods-PNObject_Example/StrongestPasswordValidator.framework"
install_framework "Pods-PNObject_Example/UIDevice_Utils.framework"
install_framework "Pods-PNObject_Example/nv_ios_http_status.framework"
@ -121,6 +122,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "Pods-PNObject_Example/PEAR_FileManager_iOS.framework"
install_framework "Pods-PNObject_Example/PNObject.framework"
install_framework "Pods-PNObject_Example/PureLayout.framework"
install_framework "Pods-PNObject_Example/RZDataBinding.framework"
install_framework "Pods-PNObject_Example/StrongestPasswordValidator.framework"
install_framework "Pods-PNObject_Example/UIDevice_Utils.framework"
install_framework "Pods-PNObject_Example/nv_ios_http_status.framework"

View File

@ -1,6 +1,6 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RZDataBinding.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "RZDataBinding" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Example
PODS_ROOT = ${SRCROOT}/Pods

View File

@ -1,6 +1,6 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RZDataBinding.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "RZDataBinding" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Example
PODS_ROOT = ${SRCROOT}/Pods

View File

@ -320,6 +320,32 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
## RZDataBinding
Copyright 2014 Raizlabs and other contributors
http://raizlabs.com/
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.
## StrongestPasswordValidator
Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>

View File

@ -387,6 +387,36 @@ THE SOFTWARE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>
Copyright 2014 Raizlabs and other contributors
http://raizlabs.com/
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.
</string>
<key>Title</key>
<string>RZDataBinding</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2016 Giuseppe Nucifora &lt;me@giuseppenucifora.com&gt;

View File

@ -99,6 +99,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "Pods-PNObject_Tests/NSUserDefaults_AESEncryptor.framework"
install_framework "Pods-PNObject_Tests/PEAR_FileManager_iOS.framework"
install_framework "Pods-PNObject_Tests/PNObject.framework"
install_framework "Pods-PNObject_Tests/RZDataBinding.framework"
install_framework "Pods-PNObject_Tests/StrongestPasswordValidator.framework"
install_framework "Pods-PNObject_Tests/UIDevice_Utils.framework"
install_framework "Pods-PNObject_Tests/nv_ios_http_status.framework"
@ -123,6 +124,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "Pods-PNObject_Tests/NSUserDefaults_AESEncryptor.framework"
install_framework "Pods-PNObject_Tests/PEAR_FileManager_iOS.framework"
install_framework "Pods-PNObject_Tests/PNObject.framework"
install_framework "Pods-PNObject_Tests/RZDataBinding.framework"
install_framework "Pods-PNObject_Tests/StrongestPasswordValidator.framework"
install_framework "Pods-PNObject_Tests/UIDevice_Utils.framework"
install_framework "Pods-PNObject_Tests/nv_ios_http_status.framework"

View File

@ -1,8 +1,8 @@
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RZDataBinding.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "RZDataBinding" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Tests
PODS_ROOT = ${SRCROOT}/Pods

View File

@ -1,8 +1,8 @@
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CocoaSecurity.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DJLocalization.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/JRSwizzle.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NACrypto.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSUserDefaults_AESEncryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RZDataBinding.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CocoaSecurity" -framework "CodFis_Helper" -framework "DJLocalization" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "JRSwizzle" -framework "NACrypto" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "NSUserDefaults_AESEncryptor" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "RZDataBinding" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Tests
PODS_ROOT = ${SRCROOT}/Pods

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_RZDataBinding : NSObject
@end
@implementation PodsDummy_RZDataBinding
@end

View File

@ -0,0 +1,4 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif

View File

@ -0,0 +1,11 @@
#import <UIKit/UIKit.h>
#import "NSObject+RZDataBinding.h"
#import "RZDataBinding.h"
#import "RZDBCoalesce.h"
#import "RZDBMacros.h"
#import "RZDBTransforms.h"
FOUNDATION_EXPORT double RZDataBindingVersionNumber;
FOUNDATION_EXPORT const unsigned char RZDataBindingVersionString[];

View File

@ -0,0 +1,6 @@
framework module RZDataBinding {
umbrella header "RZDataBinding-umbrella.h"
export *
module * { export * }
}

View File

@ -0,0 +1,4 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RZDataBinding" "${PODS_ROOT}/Headers/Public"
PODS_ROOT = ${SRCROOT}
SKIP_INSTALL = YES

View File

@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = "PNObject"
s.version = "0.5.7"
s.version = "0.6.0"
s.summary = "PNObject is a simple replica of the more complex ParseObject"
# This description is used to generate tags and improve search results.
@ -45,6 +45,7 @@ s.dependency 'FBSDKLoginKit'
s.dependency 'NACrypto'
s.dependency 'NSUserDefaults-AESEncryptor'
s.dependency 'DJLocalization'
s.dependency 'RZDataBinding'
end

View File

@ -20,7 +20,7 @@
@implementation PNInstallation
static PNInstallation *INSTALLATION = nil;
static id INSTALLATION = nil;
static bool isFirstAccess = YES;
@ -73,7 +73,7 @@ static bool isFirstAccess = YES;
PNInstallationType response = PNInstallationTypeNone;
_deviceTokenData = deviceTokenData;
self.deviceTokenData = deviceTokenData;
NSString *ptoken = [[[[deviceTokenData description]
stringByReplacingOccurrencesOfString:@"<"withString:@""]
@ -88,6 +88,9 @@ static bool isFirstAccess = YES;
response = PNInstallationTypeChange;
}
/*[self setValue:_deviceToken forKey:VariableName(oldDeviceToken)];
[self setValue:ptoken forKey:VariableName(deviceToken)];
*/
_oldDeviceToken = _deviceToken;
_deviceToken = ptoken;
@ -121,16 +124,21 @@ static bool isFirstAccess = YES;
if (self) {
/*[super setValue:@"iOS" forKey:VariableName(deviceType)];
[super setValue:[[UIDevice currentDevice] model] forKey:VariableName(deviceModel)];
[super setValue:[[UIDevice currentDevice] systemVersion] forKey:VariableName(osVersion)];
[self setValue:[[UIDevice currentDevice] name] forKey:VariableName(deviceName)];
[self setValue:[[DJLocalizationSystem shared] language] forKey:VariableName(localeIdentifier)];
*/
_deviceType = @"iOS";
_deviceModel = [[UIDevice currentDevice] model];
_osVersion = [[UIDevice currentDevice] systemVersion];
_deviceName = [[UIDevice currentDevice] name];
_localeIdentifier = [[DJLocalizationSystem shared] language];
INSTALLATION = self;
}
return INSTALLATION;
return self;
}
#pragma mark -

View File

@ -86,15 +86,12 @@ static bool isFirstAccess = YES;
if (self) {
USER = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self autoLogin];
});
}
return USER;
return self;
}
- (void) setEmail:(NSString *)email {

View File

@ -10,6 +10,7 @@
#import "PNObjectConfig.h"
#import "PNObjectModel.h"
#import "PNObjectUtilities.h"
#import "PNObjectConstants.h"
#pragma mark MappingSelector Keys

View File

@ -14,6 +14,7 @@
#import "PNObject+Protected.h"
#import "objc/runtime.h"
#import "PNObject+PNObjectConnection.m"
#import <RZDataBinding/RZDataBinding.h>
#define PNOBJECT_DIR @"PNObjects"
@ -113,7 +114,9 @@ NSString * const PNObjectMappingSelector = @"selector";
if ([propertyName isEqualToString:@"description"] || [propertyName isEqualToString:@"debugDescription"]) {
continue;
}
[self addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
//[self addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
[self rz_addTarget:self action:@selector(valueChanged:) forKeyPathChange:propertyName];
NSString *propertyType = [properties valueForKey:propertyName];
@ -171,7 +174,9 @@ NSString * const PNObjectMappingSelector = @"selector";
if ([propertyName isEqualToString:@"description"] || [propertyName isEqualToString:@"debugDescription"]) {
continue;
}
[self addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
//[self addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
[self rz_addTarget:self action:@selector(valueChanged:) forKeyPathChange:propertyName];
NSString *propertyType = [properties valueForKey:propertyName];
@ -335,6 +340,10 @@ NSString * const PNObjectMappingSelector = @"selector";
NSDictionary *JSONMap = [[self class] objcetMapping];
if (self.JSON && [[self.JSON allKeys] count] == 0) {
self.JSON = [self reverseMapping];
}
for (NSString *key in JSONMap) {
if ([self.JSON objectForKey:[JSONMap objectForKey:key]]) {
@ -405,53 +414,81 @@ NSString * const PNObjectMappingSelector = @"selector";
}
#pragma mark -
/*
NSString* const kRZDBChangeKeyObject = @"RZDBChangeObject";
NSString* const kRZDBChangeKeyOld = @"RZDBChangeOld";
NSString* const kRZDBChangeKeyNew = @"RZDBChangeNew";
NSString* const kRZDBChangeKeyKeyPath = @"RZDBChangeKeyPath";
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
@try {
if ([change objectForKey:@"new"]) {
if ([[[change objectForKey:@"new"] class] isSubclassOfClass:[PNObject class]]) {
- (void) valueChanged:(NSDictionary *) value {
NSDictionary *objectDict = [(PNObject*)[change objectForKey:@"new"] reverseMapping];
if ([value objectForKey:kRZDBChangeKeyNew]) {
if ([[[value objectForKey:kRZDBChangeKeyNew] class] isSubclassOfClass:[PNObject class]]) {
[self.JSON setValue:objectDict forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
}
else {
[self.JSON setObject:[change objectForKey:@"new"] forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
NSDictionary *objectDict = [(PNObject*)[value objectForKey:kRZDBChangeKeyNew] reverseMapping];
if ([[[[self class] objcetMapping] allKeys] containsObject:[value objectForKey:kRZDBChangeKeyKeyPath]]) {
[self.JSON setValue:objectDict forKey:[[[self class] objcetMapping] objectForKey:[value objectForKey:kRZDBChangeKeyKeyPath]]];
}
}
else {
[self.JSON removeObjectForKey:[[[self class] objcetMapping] objectForKey:keyPath]];
if ([[[[self class] objcetMapping] allKeys] containsObject:[value objectForKey:kRZDBChangeKeyKeyPath]]) {
[self.JSON setValue:[value objectForKey:kRZDBChangeKeyNew] forKey:[[[self class] objcetMapping] objectForKey:[value objectForKey:kRZDBChangeKeyKeyPath]]];
}
}
}
@catch (NSException *exception) {
}
@finally {
}
}
/*
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
@try {
if ([change objectForKey:@"new"]) {
if ([[[change objectForKey:@"new"] class] isSubclassOfClass:[PNObject class]]) {
NSDictionary *objectDict = [(PNObject*)[change objectForKey:@"new"] reverseMapping];
[self.JSON setValue:objectDict forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
}
else {
[self.JSON setObject:[change objectForKey:@"new"] forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
}
}
else {
[self.JSON removeObjectForKey:[[[self class] objcetMapping] objectForKey:keyPath]];
}
}
@catch (NSException *exception) {
}
@finally {
}
}
*/
- (void)dealloc
{
NSDictionary *properties = [PNObject propertiesForClass:self.class];
/*NSDictionary *properties = [PNObject propertiesForClass:self.class];
for (NSString *propertyName in properties) {
if ([propertyName isEqualToString:@"description"] || [propertyName isEqualToString:@"debugDescription"]) {
continue;
}
for (NSString *propertyName in properties) {
if ([propertyName isEqualToString:@"description"] || [propertyName isEqualToString:@"debugDescription"]) {
continue;
}
@try {
[self removeObserver:self forKeyPath:propertyName];
}
@catch (NSException *exception) {
@try {
[self removeObserver:self forKeyPath:propertyName];
}
@catch (NSException *exception) {
}
@finally {
}
@finally {
}
}*/
}
}
_JSON = nil;
_JSONObjectMap = nil;
_objID = nil;

View File

@ -28,5 +28,6 @@
#define NSLogDebug(format, ...)
#endif
#define VariableName(arg) ([[[@""#arg stringByReplacingOccurrencesOfString:@"_" withString:@""] componentsSeparatedByString:@"."] lastObject])
#endif