NSUserDefaultsController implemented

fix for direct instance variable access without automatic notification
NSButtonCell now accepts numerical value of strings as object value
This commit is contained in:
Johannes Fortmann 2008-09-26 14:40:02 +00:00
parent dca3526cf5
commit 0bfcf7f5b2
7 changed files with 136 additions and 4 deletions

View File

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
36570F9B0E818CD5008FE1BE /* NSGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 36570F990E818CD5008FE1BE /* NSGradient.m */; };
365710650E81A10E008FE1BE /* NSGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 36570F980E818CD5008FE1BE /* NSGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
C84909370E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C84909350E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
C84909380E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C84909360E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.m */; };
C8C52C8F0E7ED1FF003F03B5 /* NSObservationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C8C52C8D0E7ED1FF003F03B5 /* NSObservationProxy.h */; };
C8C52C900E7ED1FF003F03B5 /* NSObservationProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C52C8E0E7ED1FF003F03B5 /* NSObservationProxy.m */; };
FE01A80B0C5D9BCB00AEA51A /* AppKitExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2B53FA0976075200DA0954 /* AppKitExport.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
@ -1274,6 +1276,8 @@
6ECABDF80A3FA2B700AD7F7B /* NSCustomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSCustomView.m; sourceTree = "<group>"; };
6ECABE310A40520700AD7F7B /* NSNibKeyedUnarchiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSNibKeyedUnarchiver.h; sourceTree = "<group>"; };
6ECABE320A40520700AD7F7B /* NSNibKeyedUnarchiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSNibKeyedUnarchiver.m; sourceTree = "<group>"; };
C84909350E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSUserDefaultsControllerProxy.h; sourceTree = "<group>"; };
C84909360E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSUserDefaultsControllerProxy.m; sourceTree = "<group>"; };
C8B239A20BF8EEB500CA33AF /* defaultBindingOptions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = defaultBindingOptions.plist; sourceTree = "<group>"; };
C8C52C8D0E7ED1FF003F03B5 /* NSObservationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSObservationProxy.h; sourceTree = "<group>"; };
C8C52C8E0E7ED1FF003F03B5 /* NSObservationProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSObservationProxy.m; sourceTree = "<group>"; };
@ -2522,6 +2526,8 @@
FE2A10690B4599A3006C03DE /* NSTreeController.m */,
FE2A10700B4599BD006C03DE /* NSUserDefaultsController.h */,
FE2A10710B4599BD006C03DE /* NSUserDefaultsController.m */,
C84909350E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.h */,
C84909360E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.m */,
);
path = NSController;
sourceTree = "<group>";
@ -2965,6 +2971,7 @@
FEA965B40E7EA97500413F40 /* NSBitmapImageRep-Private.h in Headers */,
C8C52C8F0E7ED1FF003F03B5 /* NSObservationProxy.h in Headers */,
365710650E81A10E008FE1BE /* NSGradient.h in Headers */,
C84909370E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3481,6 +3488,7 @@
FE66F0060E513AE8006C5796 /* CGImageProperties.m in Sources */,
C8C52C900E7ED1FF003F03B5 /* NSObservationProxy.m in Sources */,
36570F9B0E818CD5008FE1BE /* NSGradient.m in Sources */,
C84909380E8D1FB900BA6D3A /* NSUserDefaultsControllerProxy.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -338,7 +338,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
}
-(void)setObjectValue:(id <NSCopying>)value {
if ([(id)value isKindOfClass:[NSNumber class]])
if ([(id)value respondsToSelector:@selector(intValue)])
[super setState:[(NSNumber *)value intValue]];
else
[super setState:0];

View File

@ -13,7 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
NSUserDefaults *_defaults;
NSDictionary *_initialValues;
BOOL _appliesImmediately;
id _valueProxy;
}
+sharedUserDefaultsController;

View File

@ -8,6 +8,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import <AppKit/NSUserDefaultsController.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSDictionary.h>
#import <AppKit/NSUserDefaultsControllerProxy.h>
#import <Foundation/NSString.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSRaise.h>
@implementation NSUserDefaultsController
@ -28,11 +32,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
_defaults=[defaults retain];
_initialValues=[values copy];
_appliesImmediately=YES;
_valueProxy=[[NSUserDefaultsControllerProxy alloc] initWithController:self];
return self;
}
-(void)dealloc {
[_valueProxy release];
[_defaults release];
[_initialValues release];
[super dealloc];
@ -60,4 +66,23 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
_appliesImmediately=flag;
}
-(id)values {
return _valueProxy;
}
-(id)initWithCoder:(id)coder {
if(![coder allowsKeyedCoding]) {
NSUnimplementedMethod();
}
else {
BOOL sharedInstance=[coder decodeBoolForKey:@"NSSharedInstance"];
if(sharedInstance)
{
[self release];
self=[NSUserDefaultsController sharedUserDefaultsController];
}
}
return self;
}
@end

View File

@ -0,0 +1,17 @@
//
// NSUserDefaultsControllerProxy.h
// AppKit
//
// Created by Johannes Fortmann on 26.09.08.
// Copyright 2008 -. All rights reserved.
//
#import <Foundation/NSObject.h>
@class NSMutableDictionary, NSUserDefaultsController;
@interface NSUserDefaultsControllerProxy : NSObject {
NSUserDefaultsController *_controller;
NSMutableDictionary *_cachedValues;
}
-(id)initWithController:(NSUserDefaultsController*)controller;
@end

View File

@ -0,0 +1,79 @@
//
// NSUserDefaultsControllerProxy.m
// AppKit
//
// Created by Johannes Fortmann on 26.09.08.
// Copyright 2008 -. All rights reserved.
//
#import <AppKit/NSUserDefaultsControllerProxy.h>
#import <AppKit/NSUserDefaultsController.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSNotificationCenter.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSKeyValueObserving.h>
@implementation NSUserDefaultsControllerProxy
-(id)initWithController:(NSUserDefaultsController*)controller {
if(self=[super init])
{
_controller = controller;
_cachedValues=[NSMutableDictionary new];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:[_controller defaults]];
}
return self;
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_cachedValues release];
[super dealloc];
}
-(id)valueForKey:(NSString*)key
{
id value=[_cachedValues objectForKey:key];
if(!value)
{
value=[[_controller defaults] objectForKey:key];
if(!value)
value=[[_controller initialValues] objectForKey:key];
if(value)
[_cachedValues setObject:value forKey:key];
}
return value;
}
-(void)setValue:(id)value forKey:(NSString*)key
{
[self willChangeValueForKey:key];
[_cachedValues setObject:value forKey:key];
[[_controller defaults] setObject:value forKey:key];
[self didChangeValueForKey:key];
}
-(void)userDefaultsDidChange:(id)notification
{
id defaults=[_controller defaults];
for(NSString *key in [_cachedValues allKeys])
{
id val=[_cachedValues objectForKey:key];
id newVal=[defaults objectForKey:key];
if(![val isEqual:newVal])
{
[self willChangeValueForKey:key];
[_cachedValues setObject:newVal forKey:key];
[self didChangeValueForKey:key];
}
}
}
@end

View File

@ -266,13 +266,16 @@ return [self _wrapReturnValueForSelector:sel]; \
if(ivar)
{
[self willChangeValueForKey:key];
BOOL shouldNotify=[self automaticallyNotifiesObserversForKey:key];
if(shouldNotify)
[self willChangeValueForKey:key];
// if value is nil and ivar is not an object type
if(!value && ivar->ivar_type[0]!='@')
return [self setNilValueForKey:key];
[self _setValue:value toBuffer:(void*)self+ivar->ivar_offset ofType:ivar->ivar_type];
[self didChangeValueForKey:key];
if(shouldNotify)
[self didChangeValueForKey:key];
return;
}
}