我有以下方法部分
- (NSString*) GetPathForFolder:(int)folder inDomains:(int) domains {
id cls = objc_getClass("NSFileManager");
SEL defaultManagerSelector = @selector(defaultManager);
SEL urlsForDirectoryInDomainsSelector = @selector(URLsForDirectory:inDomains:);
id fileMangerHandle = objc_msgSend(cls, defaultManagerSelector);
//NSArray<NSURL *>* notUsedArray = [fileMangerHandle URLsForDirectory:folder inDomains:domains];
NSArray<NSURL *>* resultArray = (NSArray<NSURL *>*) objc_msgSend(fileMangerHandle, urlsForDirectoryInDomainsSelector, folder, domains);
return [resultArray lastObject].absoluteString;
}
使用[self GetPathForFolder:5 inDomains:1]
调用此方法
返回file:///Applications/
,这是错误的
当我取消对NSArray<NSURL *>* notUsedArray..
行的注释后,我会得到一个不同且正确的值,该值恰好与来自的值相同
在我的C版本中我没有做的调用的target-c版本有什么作用?
更新:
objc_msgSend
,因为最终会从C#中调用此方法,但是比起开始担心互操作部分,这更容易在Objective-c中首先尝试。sel_registerName
是因为在C#中运行此程序时,我将必须进行自己的注册。答案 0 :(得分:1)
您不能像这样使用objc_msgSend
,它不是可变参数函数,即使它的原型表明了这一点。编译器需要使用与该方法相同的调用约定。为此,它需要知道所有参数的确切类型。您可以通过将objc_msgSend转换为具有正确参数的函数指针类型来说明这一点。
因此,在这种情况下,您将使用以下内容:
typedef NSArray<NSURL *> *(*UrlsForDirectoryType)(id, SEL, NSUInteger, NSUIteger);
NSArray<NSURL *>* resultArray = ((UrlsForDirectoryType)objc_msgSend)(fileMangerHandle, urlsForDirectoryInDomainsSelector, folder, domains);
当然,typedef是可选的,但是那样会使整个内容更难以阅读。
要将其公开给其他编程语言,您还可以在Objective-C中编写常规的C函数并调用它们。比直接处理运行时要容易得多。