On Monday, Dec 23, 2002, at 16:03 Europe/Amsterdam, bbum@... wrote:
> On Sunday, Dec 22, 2002, at 18:20 US/Eastern, David Eppstein wrote:
>> Shouldn't this work?
>> When I try it I get a complaint that the argument should be an
>> NSString instead of a Python string. I guess this means there is a
>> signature missing somewhere? I don't understand signatures well
>> enough to correct it.
>> Really it would be better to be able to call
>> but I can see why that's unlikely to work...
> That is exactly what you *should* be able to call but for another
> problem. Actually, either form should work in the Python sense.
NSString.localizedCaseInsensitiveCompare_(a, b) has some change of
working in a future version, 'foo'.localizedCaseInsensitiveCompare_(b)
will never work. That is, unless we change the python string type which
IMHO is not advisable (and not possible: 'str.foo = 1' does not work).
> This is sort of a bug in the bridge and a feature.
> NSString.localizedCaseInsensitiveCompare_('foo', 'bar')
> ... should really work, but complains about "First argument must
> be an objective-C object, got 'foo'". I'm somewhat surprised that
> the bridge doesn't convert 'foo' to an NSString as it hits the bridge
> because it is a feature of the bridge to transparently convert Strings
> to their native ObjC/Python type as they pass across the bridge.
Hmm... You have a point here. The current code knows that the first
argument is 'self' and assumes this is already an Objective-C object.
That is easily fixed, but as you noticed below that is probably not
enough to get this to work. Clickety-click... It is pretty easy. I have
this working for NSString in my tree, I'll check it in later but am not
completely happy with the code yet. However:
>>> NSString.localizedCaseInsensitiveCompare_('FOO', 'foo')
At least some methods work just fine...
> Rethinking this, the above method call may not work in some
> situations. In particular, in class clusters it is often the case
> that you generally interact with some private subclass. For example,
> NSArray.count(someArray) will not actually do what you want because
> instances of NSArray are never directly instantiated-- just private
> In : a = NSArray.arrayWithArray_([1,2,3,4,5])
> In : a.count()
> Out: 5
> In : NSArray.count(a)
> ValueError Traceback (most recent call
> ValueError: NSInvalidArgumentException - *** -count only defined for
> abstract class. Define -[NSCFArray count]!
That's just like in 'normal' python types: If you call NSArray.count
you get the count method defined by NSArray instead of the one defined
by the class of your object. That is not very Objective-C-like, but
this is needed to implement super(cls, self).count().
> So-- given that we can't call the methods on NSString via the
> class object, we really need to be able to pass an NSString across the
> bridge such that it remains an NSString on the Python side. There
> are a number of reasons for this-- not duplicating data and having
> access to the localization methods being the primary reasons.
> A workaround (for David and others, not a recommendation for a
> possible solution in the bridge):
> Create an NSBundle that contains a category or class that wraps
> the methods on NSString that you need access to. I.e....
> @implementation NSString (BridgedMethods)
> + (NSComparisonResult)string: (NSString *) aString
> localizedCaseInsensitiveCompare:(NSString *)bString;
> return [aString localizedCaseInsensitiveCompare: bString];
> ... to be invoked [after loading] as ...
> NSString.string_localizedCaseInsensitiveCompare_('foo', 'bar')
> ... not as elegant as an instance method and not directly compatible
> with the various sorting methods on Array and the like
That's not really a problem, just use the strint literal
"localizedCaseInsentiveCompare:" as the argument off
NSArray.sortedArrayUsingSelector_. By the time strings NSArray methods
touch the strings in an array they will be converted to NSString
(that's even true if the NSArray is the OC_PythonArray proxy for a