mirror of
https://github.com/darlinghq/darling-cocotron.git
synced 2024-11-27 14:00:22 +00:00
some NSArrayController fixes: there's probably still a lot of stuff broken, but now addObject: should be a lot faster
This commit is contained in:
parent
73953849e3
commit
aa1dbec7f6
@ -16,6 +16,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
#import <Foundation/NSKeyValueObserving.h>
|
||||
#import <Foundation/NSKeyValueCoding.h>
|
||||
#import <Foundation/NSString+KVCAdditions.h>
|
||||
#import <Foundation/NSRaise.h>
|
||||
#import "NSObservationProxy.h"
|
||||
|
||||
@interface NSObjectController(private)
|
||||
@ -30,15 +31,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
- (void)_setContentArray:(id)value;
|
||||
@end
|
||||
|
||||
@interface NSArray (private)
|
||||
-(NSUInteger)_insertObject:(id)obj inArraySortedByDescriptors:(id)desc;
|
||||
@end
|
||||
|
||||
@implementation NSArrayController
|
||||
|
||||
+(void)initialize
|
||||
{
|
||||
[self setKeys:[NSArray arrayWithObjects:@"contentArray", @"selectionIndexes", nil]
|
||||
[self setKeys:[NSArray arrayWithObjects:@"content", nil]
|
||||
triggerChangeNotificationsForDependentKey:@"contentArray"];
|
||||
[self setKeys:[NSArray arrayWithObjects:@"content", @"contentArray", @"selectionIndexes", nil]
|
||||
triggerChangeNotificationsForDependentKey:@"selection"];
|
||||
[self setKeys:[NSArray arrayWithObjects:@"contentArray", @"selectionIndexes", @"selection", nil]
|
||||
[self setKeys:[NSArray arrayWithObjects:@"content", @"contentArray", @"selectionIndexes", @"selection", nil]
|
||||
triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
[self setKeys:[NSArray arrayWithObjects:@"contentArray", @"selectionIndexes", @"selection", nil]
|
||||
[self setKeys:[NSArray arrayWithObjects:@"content", @"contentArray", @"selectionIndexes", @"selection", nil]
|
||||
triggerChangeNotificationsForDependentKey:@"selectedObjects"];
|
||||
|
||||
[self setKeys:[NSArray arrayWithObjects:@"selectionIndexes", nil]
|
||||
@ -103,17 +110,22 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
_flags.preservesSelection=value;
|
||||
}
|
||||
|
||||
- (void)_setContentArray:(id)value
|
||||
-(void)setContent:(id)value
|
||||
{
|
||||
if(![value isKindOfClass:[NSArray class]])
|
||||
value=[NSArray arrayWithObject:value];
|
||||
|
||||
id oldSelection=nil;
|
||||
id oldSelectionIndexes=[[[self selectionIndexes] copy] autorelease];
|
||||
if([self preservesSelection])
|
||||
oldSelection=[self selectedObjects];
|
||||
|
||||
[self setContent:value];
|
||||
|
||||
[super setContent:[[value mutableCopy] autorelease]];
|
||||
if(_flags.clearsFilterPredicateOnInsertion)
|
||||
[self setFilterPredicate:nil];
|
||||
|
||||
[self rearrangeObjects];
|
||||
|
||||
|
||||
|
||||
if(oldSelection)
|
||||
{
|
||||
[self setSelectedObjects:oldSelection];
|
||||
@ -124,6 +136,16 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_setContentArrayForMultipleSelection:(id)value
|
||||
{
|
||||
NSUnimplementedMethod();
|
||||
}
|
||||
|
||||
- (void)_setContentArray:(id)value
|
||||
{
|
||||
[self setContent:value];
|
||||
}
|
||||
|
||||
- (id)contentArray {
|
||||
return [self content];
|
||||
}
|
||||
@ -145,9 +167,9 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
|
||||
- (void)_setArrangedObjects:(id)value {
|
||||
if (_arrangedObjects != value)
|
||||
{
|
||||
[_arrangedObjects release];
|
||||
_arrangedObjects = [[_NSObservableArray alloc] initWithArray:value];
|
||||
{
|
||||
[_arrangedObjects release];
|
||||
_arrangedObjects = [[_NSObservableArray alloc] initWithArray:value];
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +329,7 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
|
||||
-(void)_setContentSet:(NSSet*)set
|
||||
{
|
||||
[self _setContentArray:[set allObjects]];
|
||||
[self setContent:[set allObjects]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@ -317,7 +339,21 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
{
|
||||
if(![self canAdd])
|
||||
return;
|
||||
[[self mutableArrayValueForKey:@"contentArray"] addObject:object];
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[_content addObject:object];
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if(_flags.clearsFilterPredicateOnInsertion)
|
||||
[self setFilterPredicate:nil];
|
||||
|
||||
if([_filterPredicate evaluateWithObject:object])
|
||||
{
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
NSUInteger pos=[_arrangedObjects _insertObject:object inArraySortedByDescriptors:_sortDescriptors];
|
||||
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -325,7 +361,19 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
{
|
||||
if(![self canRemove])
|
||||
return;
|
||||
[[self mutableArrayValueForKey:@"contentArray"] removeObject:object];
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[_content removeObject:object];
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if([_filterPredicate evaluateWithObject:object])
|
||||
{
|
||||
NSUInteger pos=[_arrangedObjects indexOfObject:object];
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
[_arrangedObjects removeObject:object];
|
||||
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)add:(id)sender
|
||||
@ -349,14 +397,16 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
|
||||
-(void)remove:(id)sender
|
||||
{
|
||||
[self removeObjectsAtArrangedObjectIndexes:[self selectionIndexes]];
|
||||
[self removeObjects:[[self contentArray] objectsAtIndexes:[self selectionIndexes]]];
|
||||
}
|
||||
|
||||
-(void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet*)indexes
|
||||
{
|
||||
// FIXME: this should remove no matter what canRemove returns
|
||||
[self removeObjects:[[self contentArray] objectsAtIndexes:indexes]];
|
||||
}
|
||||
|
||||
|
||||
- (void)addObjects:(NSArray *)objects
|
||||
{
|
||||
if(![self canAdd])
|
||||
@ -366,7 +416,7 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
int i;
|
||||
for(i=0; i<count; i++)
|
||||
[contentArray addObject:[objects objectAtIndex:i]];
|
||||
[self _setContentArray:contentArray];
|
||||
[self setContent:contentArray];
|
||||
}
|
||||
|
||||
|
||||
@ -381,7 +431,7 @@ triggerChangeNotificationsForDependentKey:@"selectionIndex"];
|
||||
|
||||
for(i=0; i<count; i++)
|
||||
[contentArray removeObject:[objects objectAtIndex:i]];
|
||||
[self _setContentArray:contentArray];
|
||||
[self setContent:contentArray];
|
||||
}
|
||||
|
||||
-(BOOL)canInsert;
|
||||
|
@ -14,7 +14,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
@interface NSControllerSelectionProxy : NSObject
|
||||
{
|
||||
id _controller;
|
||||
NSMutableDictionary *_values;
|
||||
NSMutableDictionary *_cachedValues;
|
||||
NSMutableArray *_observationProxies;
|
||||
id _keys;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
{
|
||||
if((self=[super init]))
|
||||
{
|
||||
_values=[NSMutableDictionary new];
|
||||
_cachedValues=[NSMutableDictionary new];
|
||||
_controller = [cont retain];
|
||||
_observationProxies = [NSMutableArray new];
|
||||
}
|
||||
@ -32,7 +32,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
-(void)dealloc
|
||||
{
|
||||
[_keys release];
|
||||
[_values release];
|
||||
[_cachedValues release];
|
||||
[_controller release];
|
||||
|
||||
if([_observationProxies count]>0)
|
||||
@ -47,7 +47,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(id)valueForKey:(NSString*)key
|
||||
{
|
||||
id val=[_values objectForKey:key];
|
||||
id val=[_cachedValues objectForKey:key];
|
||||
if(val)
|
||||
return val;
|
||||
id allValues=[[_controller selectedObjects] valueForKeyPath:key];
|
||||
@ -81,19 +81,19 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
}
|
||||
}
|
||||
|
||||
[_values setValue:val forKey:key];
|
||||
[_cachedValues setValue:val forKey:key];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
-(int)count
|
||||
{
|
||||
return [_values count];
|
||||
return [_cachedValues count];
|
||||
}
|
||||
|
||||
-(id)keyEnumerator
|
||||
{
|
||||
return [_values keyEnumerator];
|
||||
return [_cachedValues keyEnumerator];
|
||||
}
|
||||
|
||||
-(void)setValue:(id)value forKey:(NSString *)key
|
||||
@ -112,17 +112,17 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
-(void)controllerWillChange
|
||||
{
|
||||
[_keys autorelease];
|
||||
_keys=[[_values allKeys] retain];
|
||||
_keys=[[_cachedValues allKeys] retain];
|
||||
for(id key in _keys)
|
||||
{
|
||||
[self willChangeValueForKey:key];
|
||||
}
|
||||
[_values removeAllObjects];
|
||||
[_cachedValues removeAllObjects];
|
||||
}
|
||||
|
||||
-(void)controllerDidChange
|
||||
{
|
||||
[_values removeAllObjects];
|
||||
[_cachedValues removeAllObjects];
|
||||
for(id key in _keys)
|
||||
{
|
||||
[self didChangeValueForKey:key];
|
||||
@ -136,12 +136,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
[_values removeObjectForKey:keyPath];
|
||||
// remove cached value for this key path
|
||||
[_cachedValues removeObjectForKey:keyPath];
|
||||
}
|
||||
|
||||
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
|
||||
{
|
||||
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath observer:observer object:self];
|
||||
[proxy setNotifiyObject:YES];
|
||||
[_observationProxies addObject:proxy];
|
||||
|
||||
[[_controller selectedObjects] addObserver:proxy forKeyPath:keyPath options:options context:context];
|
||||
|
@ -6,7 +6,7 @@ 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. */
|
||||
#import <AppKit/NSController.h>
|
||||
@class NSString,NSPredicate,NSFetchRequest,NSManagedObjectContext,NSMenuItem,NSError,NSArray;
|
||||
@class NSString,NSPredicate,NSFetchRequest,NSManagedObjectContext,NSMenuItem,NSError,NSArray, NSCountedSet;
|
||||
|
||||
@interface NSObjectController : NSController {
|
||||
NSString* _objectClassName;
|
||||
@ -14,6 +14,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
id _selection;
|
||||
BOOL _editable;
|
||||
BOOL _automaticallyPreparesContent;
|
||||
NSCountedSet* _observedKeys;
|
||||
}
|
||||
-(void)setContent:content;
|
||||
-content;
|
||||
|
@ -36,6 +36,7 @@ triggerChangeNotificationsForDependentKey:@"canRemove"];
|
||||
_objectClassName=[[coder decodeObjectForKey:@"NSObjectClassName"] retain];
|
||||
_editable = [coder decodeBoolForKey:@"NSEditable"];
|
||||
_automaticallyPreparesContent = [coder decodeBoolForKey:@"NSAutomaticallyPreparesContent"];
|
||||
_observedKeys=[[NSCountedSet alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -45,7 +46,8 @@ triggerChangeNotificationsForDependentKey:@"canRemove"];
|
||||
}
|
||||
|
||||
- (void)setContent:(id)value {
|
||||
if (_content != value) {
|
||||
if(value!=_content)
|
||||
{
|
||||
[self _selectionWillChange];
|
||||
|
||||
[_content release];
|
||||
@ -55,6 +57,15 @@ triggerChangeNotificationsForDependentKey:@"canRemove"];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)_setContentWithoutKVO:(id)value
|
||||
{
|
||||
if (_content != value) {
|
||||
[_content release];
|
||||
_content = [value retain];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-(NSArray *)selectedObjects
|
||||
{
|
||||
return [_NSObservableArray arrayWithObject:_content];
|
||||
@ -96,6 +107,7 @@ triggerChangeNotificationsForDependentKey:@"canRemove"];
|
||||
[_selection release];
|
||||
[_objectClassName release];
|
||||
[_content release];
|
||||
[_observedKeys release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@ -127,4 +139,21 @@ triggerChangeNotificationsForDependentKey:@"canRemove"];
|
||||
- (void)setAutomaticallyPreparesContent:(BOOL)value {
|
||||
_automaticallyPreparesContent = value;
|
||||
}
|
||||
|
||||
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
|
||||
{
|
||||
[_observedKeys addObject:keyPath];
|
||||
[super addObserver:observer forKeyPath:keyPath options:options context:context];
|
||||
}
|
||||
|
||||
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
|
||||
{
|
||||
[_observedKeys removeObject:keyPath];
|
||||
[super removeObserver:observer forKeyPath:keyPath];
|
||||
}
|
||||
|
||||
-(id)_observedKeys
|
||||
{
|
||||
return _observedKeys;
|
||||
}
|
||||
@end
|
||||
|
@ -1,6 +1,7 @@
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSMutableArray.h>
|
||||
#import <Foundation/NSKeyValueObserving.h>
|
||||
|
||||
@interface _NSObservationProxy : NSObject
|
||||
{
|
||||
@ -8,19 +9,24 @@
|
||||
id _observer;
|
||||
id _object;
|
||||
BOOL _notifyObject;
|
||||
// only as storage (context for _observer will be the one given in observeValueForKeyPath:)
|
||||
// FIXME: write accessors, remove @public
|
||||
@public
|
||||
void* _context;
|
||||
NSKeyValueObservingOptions _options;
|
||||
}
|
||||
-(id)initWithKeyPath:(id)keyPath observer:(id)observer object:(id)object;
|
||||
-(id)observer;
|
||||
-(id)keyPath;
|
||||
-(void)setNotifiyObject:(BOOL)val;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@interface _NSObservableArray : NSArray
|
||||
@interface _NSObservableArray : NSMutableArray
|
||||
{
|
||||
NSArray *_array;
|
||||
NSMutableArray *_array;
|
||||
NSMutableArray *_observationProxies;
|
||||
}
|
||||
-initWithObjects:(id *)objects count:(unsigned)count;
|
||||
@end
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
_keyPath=[keyPath retain];
|
||||
_observer=observer;
|
||||
_object=object;
|
||||
if([object respondsToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)])
|
||||
_notifyObject=YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -36,6 +34,21 @@
|
||||
return _keyPath;
|
||||
}
|
||||
|
||||
-(void*)context
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
-(NSKeyValueObservingOptions)options
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
|
||||
-(void)setNotifiyObject:(BOOL)val
|
||||
{
|
||||
_notifyObject=val;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if([other isMemberOfClass:isa])
|
||||
@ -53,10 +66,12 @@
|
||||
context:(void *)context
|
||||
{
|
||||
if(_notifyObject)
|
||||
{
|
||||
[_object observeValueForKeyPath:_keyPath
|
||||
ofObject:_object
|
||||
change:change
|
||||
context:context];
|
||||
}
|
||||
|
||||
[_observer observeValueForKeyPath:_keyPath
|
||||
ofObject:_object
|
||||
@ -70,8 +85,6 @@
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation _NSObservableArray
|
||||
|
||||
-(id)objectAtIndex:(unsigned)idx
|
||||
@ -117,6 +130,9 @@
|
||||
_NSObservationProxy *proxy=[[_NSObservationProxy alloc] initWithKeyPath:keyPath
|
||||
observer:observer
|
||||
object:self];
|
||||
proxy->_options=options;
|
||||
proxy->_context=context;
|
||||
|
||||
[_observationProxies addObject:proxy];
|
||||
[proxy release];
|
||||
|
||||
@ -170,5 +186,84 @@
|
||||
forKeyPath:keyPath];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)insertObject:(id)obj atIndex:(NSUInteger)idx
|
||||
{
|
||||
for(_NSObservationProxy *proxy in _observationProxies)
|
||||
{
|
||||
id keyPath=[proxy keyPath];
|
||||
BOOL isOperator=NO;
|
||||
if([keyPath hasPrefix:@"@"])
|
||||
isOperator=YES;
|
||||
|
||||
if(isOperator)
|
||||
[self willChangeValueForKey:keyPath];
|
||||
[obj addObserver:proxy
|
||||
forKeyPath:keyPath
|
||||
options:[proxy options]
|
||||
context:[proxy context]];
|
||||
if(isOperator)
|
||||
[self didChangeValueForKey:keyPath];
|
||||
|
||||
}
|
||||
[_array insertObject:obj atIndex:idx];
|
||||
}
|
||||
|
||||
-(void)removeObjectAtIndex:(NSUInteger)idx
|
||||
{
|
||||
id obj=[_array objectAtIndex:idx];
|
||||
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];
|
||||
}
|
||||
[_array removeObjectAtIndex:idx];
|
||||
}
|
||||
|
||||
-(void)addObject:(id)obj
|
||||
{
|
||||
[self insertObject:obj atIndex:[self count]];
|
||||
}
|
||||
|
||||
-(void)removeLastObject
|
||||
{
|
||||
[self removeObjectAtIndex:[self count]];
|
||||
}
|
||||
|
||||
-(void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)obj
|
||||
{
|
||||
id old=[_array objectAtIndex:idx];
|
||||
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];
|
||||
}
|
||||
[_array replaceObjectAtIndex:idx withObject:obj];
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -125,6 +125,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(BOOL)allowsEditingForRow:(int)row
|
||||
{
|
||||
if([[_rowValues objectAtIndex:row] classForCoder]==[NSDictionary class])
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user