我有以下方法部分
- (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..
行时,我得到了一个不同且正确的值,恰好与中的值相同
调用的objective-c版本做了什么,而我在c版本中没有做什么?
更新:
- 我使用
objc_msgSend
,因为这个方法最终会从C#调用,但首先在objective-C中尝试它比开始担心互操作部分更容易 - 我使用
sel_registerName
是因为在C#内部运行它时,我必须自己注册
更多关于C#和objective-C之间的互操作。这里还有一个我试图理解的java版本。
不能像这样使用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函数并调用它们。这比直接处理运行时要容易得多。