【问题标题】:How to pass NSSize and NSRect to PyObjC KVC convenience accessor如何将 NSSize 和 NSRect 传递给 PyObjC KVC 便利访问器
【发布时间】:2011-12-09 07:05:05
【问题描述】:

我正在 Lion 上的 PyObjC 中编写一些 AppKit 代码,并且我想使用特殊的 KVC 访问器样式,例如obj._.field = value 而不是 obj.setField_(value)

我已经成功地使用 KVC 设置了 NSString 和 NSDictionary 值的属性,但是我在包装 Objective-C 结构时遇到了问题,特别是 NSSize 和 NSRect。

当我尝试设置 NSSize 或 NSRect 类型的 KVC 属性时,Objective-C 层会抛出 NSInvalidArgumentException。 Cocoa 正在尝试在 Python 对象上调用 sizeValuerectValue

这是显示问题的交互式提示处的日志:

% python
Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from AppKit import *
>>> NSApplication.sharedApplication()
<NSApplication: 0x7fcf6ae071f0>
>>> w = NSWindow.alloc().init()
>>> w._.minSize = NSSize(100, 200)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/objc/_convenience.py", line 141, in __setattr__
    return self.__object.setValue_forKey_(value, key)
ValueError: NSInvalidArgumentException - Class OC_PythonObject: no such selector: sizeValue
>>> r = NSMakeRect(100, 200, 300, 400)
>>> w._.frame=r
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/objc/_convenience.py", line 141, in __setattr__
    return self.__object.setValue_forKey_(value, key)
ValueError: NSInvalidArgumentException - Class OC_PythonObject: no such selector: rectValue

PyObjC 似乎将结构包装在 OC_PythonObject 代理中,它没有实现预期的 KVC 转换器。 KVC 代码假定该值类似于 NSValue 并实现结构访问器方法。

有没有办法在 PyObjC 中设置结构值 KVC 属性?

【问题讨论】:

    标签: cocoa pyobjc key-value-coding


    【解决方案1】:

    这很简单。即使在普通的 ObjC 中,结构体在通过 KVC 传递之前也需要包装在 NSValue 中。你可以在 Python 中做同样的事情:

    >>> w._.minSize = NSValue.valueWithSize_(NSSize(100,200))
    >>> w.minSize()
    <NSSize width=100.0 height=200.0>
    >>> w._.frame = NSValue.valueWithRect_(NSMakeRect(100, 200, 300, 400))
    >>> w.frame()
    <NSRect origin=<NSPoint x=100.0 y=200.0> size=<NSSize width=300.0 height=400.0>>
    

    有关详细信息,请参阅 KVC 编程指南中的 "Wrapping and Unwrapping Structs"。此外,在执行此操作时不要忘记,并非所有类的所有属性都符合 KVC。

    【讨论】:

    • @Jay:这不是一种解决方法。这就是 Cocoa(特别是 KVC)在 Obj-C 和 PyObjC 中的工作方式
    • KVC 以这种方式工作是正确的,并且在阅读了 PyObjC 发行说明之后,我什至可以接受使 NSSize 对象与 NSValue 不兼容是设计使然。然而,对于 PyObjC 和 Objective-C 运行时之间缺乏信息传递,必须编写的额外代码仍然是一种解决方法。 PyObjC 将 Python NSSize 对象作为不透明的 OC_PythonObject 传递给 Objective-C 运行时,与传递非 Cocoa Python 对象的方式相同。如果该类实现了 sizeValue,或者 _ 代理创建了 NSValue 包装器,那么用户代码会更加清晰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2021-12-29
    • 2013-06-30
    • 2020-11-23
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多