如何处理返回NSError的PyObjC方法?

0 投票
1 回答
772 浏览
提问于 2025-04-18 13:52

我正在尝试让我的PyObjC应用在用户点击按钮时录音。我想使用AVAudioRecorder这个类。我的代码是:

@IBAction
def startRecording_(self, sender):

    audioPath = '~/Desktop/recordTest.mp3'
    audioPathStr = NSString.stringByExpandingTildeInPath(audioPath)
    audioURL = NSURL.fileURLWithPath_(audioPathStr)

    audioSettings = {'AVFormatIDKey': 'kAudioFormatAppleIMA4', 'AVSampleRateKey': 1600.0, 'AVNumberOfChannelsKey': 1 }
    audioDict = NSDictionary.dictionaryWithDictionary_(audioSettings)

    (recorder, error) = AVAudioRecorder.alloc().initWithURL_settings_error_(audioURL, audioDict, objc.nil)
    recorder.record()

当我运行上面的代码时,出现了以下错误:

<type 'exceptions.TypeError'>: 'NoneType' object is not iterable

看起来initWithURL_settings_error_这个方法的第三个参数需要一个可迭代的对象。但是,我以为在使用PyObjC的方法时,如果需要一个错误参数,我可以传入objc.nil或者None

当我在一个NSString的方法上使用类似的语法时:

(names, error) = NSString.stringWithContentsOfFile_encoding_error_(u"/usr/share/dict/propernames", NSASCIIStringEncoding, objc.nil)

代码是可以运行的。

为什么我调用AVAudioRecord方法时不行?是因为这个方法需要一个outError,而NSString的方法只需要一个error吗?

1 个回答

3

这段代码在使用AVFoundation这个类时出问题了,因为PyObjC没有关于这个框架的元数据描述。简单来说,它知道最后一个参数是一个对象的指针,但不知道这个指针是用来作为引用输出参数的。

如果你想手动检查PyObjC对这个参数的了解,可以这样做:

>> import AVFoundation
>>> AVFoundation.AVAudioRecorder.initWithURL_settings_error_.__metadata__( ['arguments'][-1]
{'null_accepted': True, 'already_retained': False, 'type': '^@', 'already_cfretained': False}

这里的类型应该是"o^@"。

这是使用苹果版本的PyObjC:你可以用“import AVFoundation”来导入这个框架,这样就会使用AVFoundation框架里的BridgeSupport数据文件。不过很遗憾,这些数据不完整,没有关于这个方法的信息,所以这里的类型就错了。

对于这个特定的方法,使用PyObjC的元数据API来修复这个问题是相对简单的:

import objc
objc.registerMetaDataForSelector(b"AVAudioRecorder", b"initWithURL:settings:error:",
        dict(
            arguments={
               4: dict(type_modifier=objc._C_OUT),
            }
        ))

不过,要修复AVFoundation的所有元数据就会复杂得多 :-(

撰写回答