objective-c语法和c语法的结果不同



我有以下方法部分

- (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版本中没有做什么?

更新:

  1. 我使用objc_msgSend,因为这个方法最终会从C#调用,但首先在objective-C中尝试它比开始担心互操作部分更容易
  2. 我使用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函数并调用它们。这比直接处理运行时要容易得多。

最新更新