_NSObservableArray unit test and many fixes

KVO now ignores '.' in keypaths starting with '@'
This commit is contained in:
Johannes Fortmann 2009-02-10 18:04:33 +00:00
parent d2f2fdfec9
commit 4eb6a80fdb
8 changed files with 348 additions and 93 deletions

View File

@ -1436,7 +1436,7 @@
C8AB730D0F40C21A00D93B96 /* NSControllerMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AB73090F40C21A00D93B96 /* NSControllerMarker.m */; };
C8AB730E0F40C21A00D93B96 /* NSControllerMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AB73080F40C21A00D93B96 /* NSControllerMarker.h */; settings = {ATTRIBUTES = (Private, ); }; };
C8AB730F0F40C21A00D93B96 /* NSControllerMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AB73090F40C21A00D93B96 /* NSControllerMarker.m */; };
C8C52C8F0E7ED1FF003F03B5 /* NSObservationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C8C52C8D0E7ED1FF003F03B5 /* NSObservationProxy.h */; };
C8C52C8F0E7ED1FF003F03B5 /* NSObservationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C8C52C8D0E7ED1FF003F03B5 /* NSObservationProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
C8C52C900E7ED1FF003F03B5 /* NSObservationProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C52C8E0E7ED1FF003F03B5 /* NSObservationProxy.m */; };
C8C995BD0F0BB2B100A0A091 /* X11AsyncInputSourceSet.h in Headers */ = {isa = PBXBuildFile; fileRef = C8C995BB0F0BB2B100A0A091 /* X11AsyncInputSourceSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
C8C995BE0F0BB2B100A0A091 /* X11AsyncInputSourceSet.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C995BC0F0BB2B100A0A091 /* X11AsyncInputSourceSet.m */; };

View File

@ -2,6 +2,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSMutableArray.h>
#import <Foundation/NSKeyValueObserving.h>
#import <Foundation/NSMutableIndexSet.h>
@interface _NSObservationProxy : NSObject
{
@ -27,6 +28,7 @@
{
NSMutableArray *_array;
NSMutableArray *_observationProxies;
NSMutableIndexSet *_roi;
}
@end

View File

@ -97,11 +97,15 @@
return [_array count];
}
-(id)init {
return [self initWithObjects:NULL count:0];
}
-initWithObjects:(id *)objects count:(unsigned)count;
{
if((self=[super init]))
{
_array=[[NSArray alloc] initWithObjects:objects count:count];
_array=[[NSMutableArray alloc] initWithObjects:objects count:count];
_observationProxies=[NSMutableArray new];
}
return self;
@ -121,70 +125,78 @@
-(void)addObserver:(id)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context;
{
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath
observer:observer
object:self];
proxy->_options=options;
proxy->_context=context;
[_observationProxies addObject:proxy];
[proxy release];
if([keyPath hasPrefix:@"@"])
{
// count never changes (immutable array)
if([keyPath isEqualToString:@"@count"])
return;
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath
observer:observer
object:self];
proxy->_options=options;
proxy->_context=context;
[_observationProxies addObject:proxy];
[proxy release];
NSString* firstPart, *rest;
[keyPath _KVC_partBeforeDot:&firstPart afterDot:&rest];
[super addObserver:observer
forKeyPath:keyPath
options:options
context:context];
[_array addObserver:proxy
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])]
forKeyPath:rest
options:options
context:context];
if(rest) {
[self addObserver:proxy
forKeyPath:rest
options:options
context:context];
}
}
else
{
[_array addObserver:observer
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])]
forKeyPath:keyPath
options:options
context:context];
}
if([_array count]) {
id idxs=_roi ? _roi : [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])];
[_array addObserver:proxy
toObjectsAtIndexes:idxs
forKeyPath:keyPath
options:options
context:context];
}
}
}
-(void)removeObserver:(id)observer forKeyPath:(NSString*)keyPath;
{
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath
observer:observer
object:self];
int idx=[_observationProxies indexOfObject:proxy];
[proxy release];
proxy=[_observationProxies objectAtIndex:idx];
if([keyPath hasPrefix:@"@"])
{
// count never changes (immutable array)
if([keyPath isEqualToString:@"@count"])
return;
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath
observer:observer
object:self];
int idx=[_observationProxies indexOfObject:proxy];
[proxy release];
proxy=[_observationProxies objectAtIndex:idx];
NSString* firstPart, *rest;
[keyPath _KVC_partBeforeDot:&firstPart afterDot:&rest];
[super removeObserver:observer
forKeyPath:keyPath];
[_array removeObserver:proxy
fromObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])]
forKeyPath:rest];
[_observationProxies removeObjectAtIndex:idx];
if(rest) {
[self removeObserver:proxy
forKeyPath:rest];
}
}
else
{
[_array removeObserver:observer
fromObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])]
forKeyPath:keyPath];
if([_array count]) {
id idxs=_roi ? _roi : [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_array count])];
[_array removeObserver:proxy
fromObjectsAtIndexes:idxs
forKeyPath:keyPath];
}
}
[_observationProxies removeObjectAtIndex:idx];
}
-(void)insertObject:(id)obj atIndex:(NSUInteger)idx
@ -192,21 +204,28 @@
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
BOOL isOperator=NO;
if([keyPath hasPrefix:@"@"])
isOperator=YES;
if(isOperator)
if([keyPath hasPrefix:@"@"])
[self willChangeValueForKey:keyPath];
[obj addObserver:proxy
forKeyPath:keyPath
options:[proxy options]
context:[proxy context]];
if(isOperator)
[self didChangeValueForKey:keyPath];
else
if(!_roi) {
[obj addObserver:proxy
forKeyPath:keyPath
options:[proxy options]
context:[proxy context]];
}
}
[_array insertObject:obj atIndex:idx];
[_roi shiftIndexesStartingAtIndex:idx by:1];
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
if([keyPath hasPrefix:@"@"])
[self didChangeValueForKey:keyPath];
}
}
-(void)removeObjectAtIndex:(NSUInteger)idx
@ -215,19 +234,28 @@
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
BOOL isOperator=NO;
if([keyPath hasPrefix:@"@"])
isOperator=YES;
if(isOperator)
[self willChangeValueForKey:keyPath];
[obj removeObserver:proxy
forKeyPath:keyPath];
if(isOperator)
[self didChangeValueForKey:keyPath];
else {
if(!_roi || [_roi containsIndex:idx]) {
[obj removeObserver:proxy
forKeyPath:keyPath];
}
}
}
[_array removeObjectAtIndex:idx];
if([_roi containsIndex:idx])
[_roi shiftIndexesStartingAtIndex:idx+1 by:-1];
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
if([keyPath hasPrefix:@"@"])
[self didChangeValueForKey:keyPath];
}
}
-(void)addObject:(id)obj
@ -237,7 +265,7 @@
-(void)removeLastObject
{
[self removeObjectAtIndex:[self count]];
[self removeObjectAtIndex:[self count]-1];
}
-(void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)obj
@ -246,24 +274,49 @@
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
BOOL isOperator=NO;
if([keyPath hasPrefix:@"@"])
isOperator=YES;
if(isOperator)
[self willChangeValueForKey:keyPath];
[old removeObserver:proxy
forKeyPath:[proxy keyPath]];
[obj addObserver:proxy
forKeyPath:[proxy keyPath]
options:[proxy options]
context:[proxy context]];
if(isOperator)
[self didChangeValueForKey:keyPath];
else {
if(!_roi || [_roi containsIndex:idx]) {
[old removeObserver:proxy
forKeyPath:[proxy keyPath]];
[obj addObserver:proxy
forKeyPath:[proxy keyPath]
options:[proxy options]
context:[proxy context]];
}
}
}
[_array replaceObjectAtIndex:idx withObject:obj];
for(_NSObservationProxy *proxy in _observationProxies)
{
id keyPath=[proxy keyPath];
if([keyPath hasPrefix:@"@"])
[self didChangeValueForKey:keyPath];
}
}
-(void)setROI:(NSIndexSet*)newROI {
if(newROI != _roi) {
id proxies=[_observationProxies copy];
for(_NSObservationProxy *proxy in proxies) {
[self removeObserver:[proxy observer] forKeyPath:[proxy keyPath]];
}
[_roi release];
_roi=[newROI mutableCopy];
for(_NSObservationProxy *proxy in proxies) {
[self addObserver:[proxy observer] forKeyPath:[proxy keyPath] options:[proxy options] context:[proxy context]];
}
[proxies release];
}
}
@end

View File

@ -33,4 +33,5 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)selectItemWithTitle:(NSString *)title;
- (NSMenuItem *)lastItem;
@end

View File

@ -83,6 +83,12 @@ static NSLock *kvoLock=nil;
NSString* key;
[keyPath _KVC_partBeforeDot:&key afterDot:&remainingKeyPath];
if([keyPath hasPrefix:@"@"]) {
// the key path is an operator: don't evaluate
key=keyPath;
remainingKeyPath=nil;
}
// get observation info dictionary
NSMutableDictionary* observationInfo=[self observationInfo];
// get all observers for current key
@ -208,6 +214,12 @@ static NSLock *kvoLock=nil;
{
NSString* key, *remainingKeyPath;
[keyPath _KVC_partBeforeDot:&key afterDot:&remainingKeyPath];
if([keyPath hasPrefix:@"@"]) {
// the key path is an operator: don't evaluate
key=keyPath;
remainingKeyPath=nil;
}
// now remove own observer
NSMutableDictionary* observationInfo=[self observationInfo];
@ -229,7 +241,7 @@ static NSLock *kvoLock=nil;
[observationInfo release];
}
if(remainingKeyPath)
if([remainingKeyPath length])
[[self valueForKey:key] removeObserver:info forKeyPath:remainingKeyPath];
NSSet* keysPathsForKey=[isa keyPathsForValuesAffectingValueForKey:key];
@ -336,6 +348,12 @@ static NSLock *kvoLock=nil;
NSString* firstPart, *rest;
[keyPath _KVC_partBeforeDot:&firstPart afterDot:&rest];
if([keyPath hasPrefix:@"@"]) {
// the key path is an operator: don't evaluate
key=keyPath;
rest=nil;
}
// remove deeper levels (those items will change)
if(rest)
@ -382,6 +400,12 @@ static NSLock *kvoLock=nil;
// restore deeper observers if applicable
NSString* firstPart, *rest;
[keyPath _KVC_partBeforeDot:&firstPart afterDot:&rest];
if([keyPath hasPrefix:@"@"]) {
// the key path is an operator: don't evaluate
key=keyPath;
rest=nil;
}
if(rest)
{

View File

@ -0,0 +1,20 @@
//
// ObservableArray.h
// UnitTests
//
// Created by Johannes Fortmann on 10.02.09.
// Copyright 2009 -. All rights reserved.
//
#import <SenTestingKit/SenTestingKit.h>
@interface _NSObservableArray : NSMutableArray
-(void)setROI:(id)roi;
@end
@interface ObservableArray : SenTestCase {
_NSObservableArray *_array;
id _lastObservedKey;
}
@property (copy) NSString* lastObservedKey;
@end

View File

@ -0,0 +1,153 @@
//
// ObservableArray.m
// UnitTests
//
// Created by Johannes Fortmann on 10.02.09.
// Copyright 2009 -. All rights reserved.
//
#import "ObservableArray.h"
#define AssertLastKeyWas(a) STAssertEqualObjects(self.lastObservedKey, a, nil); self.lastObservedKey=nil;
void* ObservableArrayTestContext;
@implementation ObservableArray
@synthesize lastObservedKey=_lastObservedKey;
-(void)setUp {
_array=[[NSClassFromString(@"_NSObservableArray") alloc] init];
if(!_array)
return;
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"First", @"name",
[NSNumber numberWithInt:10], @"value",
nil]];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Second", @"name",
[NSNumber numberWithInt:20], @"value",
nil]];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Third", @"name",
[NSNumber numberWithInt:30], @"value",
nil]];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Fourth", @"name",
[NSNumber numberWithInt:40], @"value",
nil]];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Fifth", @"name",
[NSNumber numberWithInt:50], @"value",
nil]];
[_array addObserver:self forKeyPath:@"name" options:0 context:&ObservableArrayTestContext];
[_array addObserver:self forKeyPath:@"value" options:0 context:&ObservableArrayTestContext];
}
-(void)testArrayMutation {
if(!_array)
return;
[_array addObserver:self forKeyPath:@"@count" options:0 context:&ObservableArrayTestContext];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Sixth", @"name",
[NSNumber numberWithInt:60], @"value",
nil]];
AssertLastKeyWas(@"@count");
[_array removeLastObject];
AssertLastKeyWas(@"@count");
[_array replaceObjectAtIndex:3 withObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Sixth", @"name",
[NSNumber numberWithInt:60], @"value",
nil]];
AssertLastKeyWas(@"@count");
[_array removeObserver:self forKeyPath:@"@count"];
}
-(void)testArrayOperatorMutation {
[_array addObserver:self forKeyPath:@"@avg.value" options:0 context:&ObservableArrayTestContext];
[_array addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Sixth", @"name",
[NSNumber numberWithInt:60], @"value",
nil]];
AssertLastKeyWas(@"@avg.value");
[[_array objectAtIndex:0] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(@"@avg.value");
[_array removeObserver:self forKeyPath:@"@avg.value"];
}
-(void)testArraySimpleMutation {
[_array addObserver:self forKeyPath:@"value" options:0 context:&ObservableArrayTestContext];
[[_array objectAtIndex:0] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(@"value");
[_array removeObserver:self forKeyPath:@"value"];
}
-(void)testROI {
[_array addObserver:self forKeyPath:@"value" options:0 context:&ObservableArrayTestContext];
id indexes=[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)];
id irrelevant=[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
[irrelevant addIndexesInRange:NSMakeRange(4, [_array count]-4)];
[_array setROI:indexes];
for(int i=[indexes firstIndex]; i!=NSNotFound; i=[indexes indexGreaterThanIndex:i]) {
[[_array objectAtIndex:i] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(@"value");
}
for(int i=[irrelevant firstIndex]; i!=NSNotFound; i=[irrelevant indexGreaterThanIndex:i]) {
[[_array objectAtIndex:i] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(nil);
}
[_array removeObjectAtIndex:1];
[_array insertObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Sixth", @"name",
[NSNumber numberWithInt:60], @"value",
nil]
atIndex:1];
for(int i=[indexes firstIndex]; i!=NSNotFound; i=[indexes indexGreaterThanIndex:i]) {
[[_array objectAtIndex:i] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(@"value");
}
for(int i=[irrelevant firstIndex]; i!=NSNotFound; i=[irrelevant indexGreaterThanIndex:i]) {
[[_array objectAtIndex:i] setValue:[NSNumber numberWithInt:0] forKey:@"value"];
AssertLastKeyWas(nil);
}
[_array removeObserver:self forKeyPath:@"value"];
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == &ObservableArrayTestContext) {
self.lastObservedKey=keyPath;
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)tearDown {
self.lastObservedKey=nil;
[_array removeObserver:self forKeyPath:@"name"];
[_array removeObserver:self forKeyPath:@"value"];
for(id item in _array) {
STAssertEqualObjects([item observationInfo], nil, nil);
}
[_array release];
}
@end

View File

@ -18,9 +18,7 @@
C81371EC0F38FF93001D4AFB /* Binary.plist in Resources */ = {isa = PBXBuildFile; fileRef = C8A392D70E48B26200A9C289 /* Binary.plist */; };
C81371ED0F38FF93001D4AFB /* TextFieldBindings.xib in Resources */ = {isa = PBXBuildFile; fileRef = C82950000F2CC4AA00F0DAF2 /* TextFieldBindings.xib */; };
C81371EE0F38FF9A001D4AFB /* CrashCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C80F9D160E59E45100ECD487 /* CrashCatcher.m */; };
C81371F00F38FF9A001D4AFB /* KVC.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C802800DB51FEF0089C0D7 /* KVC.m */; };
C81371F10F38FF9A001D4AFB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C897902B0ECA1E5400C3E5EE /* main.m */; };
C81371F30F38FF9A001D4AFB /* KeyedArchiving.m in Sources */ = {isa = PBXBuildFile; fileRef = C813714C0F38FA61001D4AFB /* KeyedArchiving.m */; };
C81373B60F3A15D2001D4AFB /* Apple.bplist.keyedArchive in Resources */ = {isa = PBXBuildFile; fileRef = C81373B50F3A15D2001D4AFB /* Apple.bplist.keyedArchive */; };
C81373B70F3A15D2001D4AFB /* Apple.bplist.keyedArchive in Resources */ = {isa = PBXBuildFile; fileRef = C81373B50F3A15D2001D4AFB /* Apple.bplist.keyedArchive */; };
C81373B80F3A15D2001D4AFB /* Apple.bplist.keyedArchive in Resources */ = {isa = PBXBuildFile; fileRef = C81373B50F3A15D2001D4AFB /* Apple.bplist.keyedArchive */; };
@ -45,6 +43,11 @@
C8794B900EE4727C00539601 /* KVC.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C802800DB51FEF0089C0D7 /* KVC.m */; };
C8794B910EE4727C00539601 /* Properties.m in Sources */ = {isa = PBXBuildFile; fileRef = C827EB3A0DB63FFA00360D99 /* Properties.m */; };
C8794B920EE4727C00539601 /* ForEach.m in Sources */ = {isa = PBXBuildFile; fileRef = C88B859B0DB90282000A8500 /* ForEach.m */; };
C88255850F419397002ED1DA /* ObservableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = C88255840F419397002ED1DA /* ObservableArray.m */; };
C88255860F419397002ED1DA /* ObservableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = C88255840F419397002ED1DA /* ObservableArray.m */; };
C88255870F419397002ED1DA /* ObservableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = C88255840F419397002ED1DA /* ObservableArray.m */; };
C88255880F419397002ED1DA /* ObservableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = C88255840F419397002ED1DA /* ObservableArray.m */; };
C88256C00F41A869002ED1DA /* KVO.m in Sources */ = {isa = PBXBuildFile; fileRef = C88470DA0DD3A9F600853747 /* KVO.m */; };
C897902C0ECA1E5400C3E5EE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C897902B0ECA1E5400C3E5EE /* main.m */; };
C897902E0ECA1E5400C3E5EE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C897902B0ECA1E5400C3E5EE /* main.m */; };
C89790710ECA202F00C3E5EE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 089C1672FE841209C02AAC07 /* Foundation.framework */; };
@ -65,14 +68,11 @@
C8C803100DB52A010089C0D7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 089C1672FE841209C02AAC07 /* Foundation.framework */; };
C8D197020ECCD487005B24B1 /* Runloop.m in Sources */ = {isa = PBXBuildFile; fileRef = C81F5A3F0DD22B94006F82C7 /* Runloop.m */; };
C8DA2D100F4074E3006E73E9 /* TextFieldBindings.m in Sources */ = {isa = PBXBuildFile; fileRef = C8294FF50F2CC47700F0DAF2 /* TextFieldBindings.m */; };
C8DA2D110F4074E4006E73E9 /* TextFieldBindings.m in Sources */ = {isa = PBXBuildFile; fileRef = C8294FF50F2CC47700F0DAF2 /* TextFieldBindings.m */; };
C8DA2D220F407516006E73E9 /* TableViewTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D210F407516006E73E9 /* TableViewTest.m */; };
C8DA2D230F407516006E73E9 /* TableViewTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D210F407516006E73E9 /* TableViewTest.m */; };
C8DA2D240F407516006E73E9 /* TableViewTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D210F407516006E73E9 /* TableViewTest.m */; };
C8DA2D250F407516006E73E9 /* TableViewTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D210F407516006E73E9 /* TableViewTest.m */; };
C8DA2D2D0F40757F006E73E9 /* NibBasedTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D2C0F40757F006E73E9 /* NibBasedTest.m */; };
C8DA2D2E0F40757F006E73E9 /* NibBasedTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D2C0F40757F006E73E9 /* NibBasedTest.m */; };
C8DA2D2F0F40757F006E73E9 /* NibBasedTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D2C0F40757F006E73E9 /* NibBasedTest.m */; };
C8DA2D300F40757F006E73E9 /* NibBasedTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2D2C0F40757F006E73E9 /* NibBasedTest.m */; };
C8DA2D530F40761B006E73E9 /* TableViewTest.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8DA2D520F40761B006E73E9 /* TableViewTest.xib */; };
C8DA2D540F40761B006E73E9 /* TableViewTest.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8DA2D520F40761B006E73E9 /* TableViewTest.xib */; };
@ -80,7 +80,6 @@
C8DA2D560F40761B006E73E9 /* TableViewTest.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8DA2D520F40761B006E73E9 /* TableViewTest.xib */; };
C8DA2EC30F408EAB006E73E9 /* Predicate.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2EC20F408EAB006E73E9 /* Predicate.m */; };
C8DA2EC40F408EAB006E73E9 /* Predicate.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2EC20F408EAB006E73E9 /* Predicate.m */; };
C8DA2EC50F408EAB006E73E9 /* Predicate.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2EC20F408EAB006E73E9 /* Predicate.m */; };
C8DA2EC60F408EAB006E73E9 /* Predicate.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DA2EC20F408EAB006E73E9 /* Predicate.m */; };
C8EA126C0E8941490051F4DF /* CrashCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C80F9D160E59E45100ECD487 /* CrashCatcher.m */; };
C8EA126E0E89414E0051F4DF /* Binary.plist in Resources */ = {isa = PBXBuildFile; fileRef = C8A392D70E48B26200A9C289 /* Binary.plist */; };
@ -158,6 +157,8 @@
C84F02C10E1F8F17000C03D6 /* ObjCXXExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjCXXExceptions.h; sourceTree = "<group>"; };
C84F02C20E1F8F17000C03D6 /* ObjCXXExceptions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ObjCXXExceptions.mm; sourceTree = "<group>"; };
C85D1F910DBBBAD7005A5FD6 /* UnitTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
C88255830F419397002ED1DA /* ObservableArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObservableArray.h; sourceTree = "<group>"; };
C88255840F419397002ED1DA /* ObservableArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObservableArray.m; sourceTree = "<group>"; };
C88470D90DD3A9F600853747 /* KVO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVO.h; sourceTree = "<group>"; };
C88470DA0DD3A9F600853747 /* KVO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVO.m; sourceTree = "<group>"; };
C88B859A0DB90282000A8500 /* ForEach.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ForEach.h; sourceTree = "<group>"; };
@ -368,6 +369,8 @@
C8DA2D520F40761B006E73E9 /* TableViewTest.xib */,
C8DA2D2B0F40757F006E73E9 /* NibBasedTest.h */,
C8DA2D2C0F40757F006E73E9 /* NibBasedTest.m */,
C88255830F419397002ED1DA /* ObservableArray.h */,
C88255840F419397002ED1DA /* ObservableArray.m */,
);
path = Bindings;
sourceTree = "<group>";
@ -608,6 +611,7 @@
C8DA2D220F407516006E73E9 /* TableViewTest.m in Sources */,
C8DA2D2D0F40757F006E73E9 /* NibBasedTest.m in Sources */,
C8DA2EC30F408EAB006E73E9 /* Predicate.m in Sources */,
C88255870F419397002ED1DA /* ObservableArray.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -616,13 +620,9 @@
buildActionMask = 2147483647;
files = (
C81371EE0F38FF9A001D4AFB /* CrashCatcher.m in Sources */,
C81371F00F38FF9A001D4AFB /* KVC.m in Sources */,
C81371F10F38FF9A001D4AFB /* main.m in Sources */,
C81371F30F38FF9A001D4AFB /* KeyedArchiving.m in Sources */,
C8DA2D110F4074E4006E73E9 /* TextFieldBindings.m in Sources */,
C8DA2D240F407516006E73E9 /* TableViewTest.m in Sources */,
C8DA2D2F0F40757F006E73E9 /* NibBasedTest.m in Sources */,
C8DA2EC50F408EAB006E73E9 /* Predicate.m in Sources */,
C88255860F419397002ED1DA /* ObservableArray.m in Sources */,
C88256C00F41A869002ED1DA /* KVO.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -638,6 +638,7 @@
C8DA2D250F407516006E73E9 /* TableViewTest.m in Sources */,
C8DA2D300F40757F006E73E9 /* NibBasedTest.m in Sources */,
C8DA2EC60F408EAB006E73E9 /* Predicate.m in Sources */,
C88255880F419397002ED1DA /* ObservableArray.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -656,6 +657,7 @@
C8DA2D230F407516006E73E9 /* TableViewTest.m in Sources */,
C8DA2D2E0F40757F006E73E9 /* NibBasedTest.m in Sources */,
C8DA2EC40F408EAB006E73E9 /* Predicate.m in Sources */,
C88255850F419397002ED1DA /* ObservableArray.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};