As usual it turns out that things are slightly more complicated. There is a tiny problem with David's test code, he did set "t" as its own object value instead of using the proxy there. When correcting this I noticed that the value from the proxy never gets used and extended the test code slightly and finally testing with different subclasses of NSCell, not just NSActionCell. They behave violently different. For NSCell and NSActionCell floatValue and doubleValue always return 0.0 even when setting this value explicitly. NSSliderCell and NSTextFieldCell behave different, but also not the same way. Looks like we will need to investigate further and most likely will need to move the actual value handling code down into the specific NSCell subclasses. This sounds very ugly to me.
Fred Am 20.02.2018 um 15:55 schrieb David Chisnall: > On 20 Feb 2018, at 14:30, Yavor Doganov <[email protected]> wrote: >> >> I think this condition is always false. _cell.has_valid_object_value >> is NO and _object_value is nil. So it jumps to NSCell.m:269 and >> SMDoubleSliderCell's -stringValue is called which calls -stringHiValue >> which in turn calls -doubleHiValue and from there the infinite >> recursion is in place. >> >> At least this is what I observe in the debugger. > > Ah, that makes sense - I’d missed that in the trace. So now the question is > what happens when you call -doubleValue on an NSCell in Cocoa when it has a > string value? Here’s a little test program that finds out: > > #import <Cocoa/Cocoa.h> > > @interface Proxy : NSProxy > { > @public > id obj; > } > @end > > @implementation Proxy > - (BOOL)respondsToSelector: (SEL)aSelector > { > return [obj respondsToSelector: aSelector]; > } > - (NSMethodSignature*)methodSignatureForSelector: (SEL)aSelector > { > return [obj methodSignatureForSelector: aSelector]; > } > - (void)forwardInvocation: (NSInvocation*)anInvocation > { > NSLog(@"%@ set to proxy", anInvocation); > [anInvocation invokeWithTarget: obj]; > } > @end > > @interface Test : NSActionCell @end > @implementation Test > - (float)floatValue > { > NSLog(@"-floatValue called\n"); > return [super floatValue]; > } > - (NSString*)stringValue > { > NSLog(@"-stringValue called\n"); > return [super stringValue]; > } > @end > > int main(void) > { > @autoreleasepool > { > Test *t = [Test new]; > Proxy *p = [Proxy alloc]; > p->obj = @"0.23"; > [t setObjectValue: t]; > NSLog(@"Querying"); > NSLog(@"%f", [t floatValue]); > } > } > > The output is: > > 2018-02-20 14:46:39.917 a.out[85231:11731363] Querying > 2018-02-20 14:46:39.917 a.out[85231:11731363] -floatValue called > 2018-02-20 14:46:39.917 a.out[85231:11731363] 0.000000 > > > So, from this we learn that Cocoa’s NSCell implementation doesn’t call any > methods on either itself or the object to find the floating point value. > This is a bit odd, but at the very least we should fix GNUstep’s NSCell to > query the object and not itself to find the string value. The correct fix is > probably: > > - (float) floatValue > { > if (_cell.has_valid_object_value == YES) > { > if ([_object_value respondsToSelector: @selector(floatValue)])) > { > return [_object_value floatValue]; > } > if ([_object_value respondsToSelector: @selector(stringValue)])) > { > return [[_object_value stringValue] floatValue]; > } > } > return 0; > } > > And apply similar fixes to the other *Value methods in NSCell. > > You can hack around this brokenness by including the above method in a > category on NSCell in your application (though please remember to remove it > once GNUstep is fixed!). > > David _______________________________________________ Discuss-gnustep mailing list [email protected] https://lists.gnu.org/mailman/listinfo/discuss-gnustep
