Objective C 类方法与 C 函数

2023-11-26

在从事开源项目时,我遇到了以下 C 函数声明和实现:

// FSNData.h
NSString *stringForMimeType(MimeType type);

@interface FSNData : NSObject
// All the expected objective-c property and instance method declarations
@end

// FSNData.m
#import "FSNData.h"

// where 'type' is an enum
// this does work as expected
NSString *stringForMimeType(MimeType type) {
    switch (type) {
        case MimeType_image_jpeg: return @"image/jpeg";
        case MimeType_image_png:  return @"image/png";
        default:
            NSLog(@"ERROR: FSNData: unknown MimeType: %d", type);

        // do not return "application/octet-stream"; instead, let the recipient guess
        // http://en.wikipedia.org/wiki/Internet_media_type
        return nil;
    }
}

@implementation

// all properties and methods defined in FSData.h implemented as expected

@end

这个例子可以很容易地重写为类级别的方法,没有任何问题。事实上,使用stringFormMimeType()sill 需要导入FSNData无论如何,头文件。

看着苹果文档,它仅指出:

因为 Objective-C 建立在 ANSI C 的基础上,所以你可以自由地 将直接 C 代码与 Objective-C 代码混合在一起。此外,你的代码 可以调用非 Cocoa 编程接口中定义的函数,例如 作为 /usr/include 中的 BSD 库接口。

没有提到 C 函数何时应该支持 Objective-C 方法。

此时我能看到的唯一好处是,与类方法相反,调用上述函数会跳过一些 Objective-C 运行时调用。在一个典型的用例中FSNData,这不会给用户(甚至可能是开发人员)带来性能的显着提升*。

与类方法相比,C 函数有什么好处(除了编码风格)?

*FSNData被用作FS网络库,所以我怀疑在任何应用程序的生命周期中都会执行成千上万的网络操作。


简而言之,C(或 C++)实现非常有用:

  • 对于抽象
  • 为了可重复使用
  • 制作中大型节目时
  • 在性能关键路径中
  • 对于“内部”实施

与类方法相比,C 函数有什么好处(除了编码风格)?

  • ObjC 消息传递引入了间接函数调用。这些是优化器的防火墙。
  • C 函数可以轻松限制访问,而“私有”ObjC 实现可能会使用 ObjC 运行时查找或意外覆盖。
  • 如果未引用,C 函数可能会从可执行文件中删除,或者可能会被设为私有。如果您编写可重用的代码(并且您应该),这可能会对您的二进制大小和加载时间产生巨大影响 - 未引用/使用的 C 函数可能会被删除,但 ObjC 类型和方法将被保留(包括它们的所有内容)参考)。这就是为什么当您仅使用 ObjC 静态库的一小部分时,您的应用程序的二进制大小可能会显着增加 - 库中的每个 objc 类都会被保留。如果该库是 C 或 C++,那么您只需很小的增长即可完成,因为您只需要引用的内容。使用 C 和 C++ 更容易证明引用或未引用的内容。
  • C 函数可以在编译期间或链接时间优化阶段内联。
  • 编译器和优化器能够对 C 函数进行很多优化(例如过程间优化),但对 ObjC 方法却很少,因为它们总是间接的。
  • 避免 ObjC 消息调度开销(正如您提到的)
  • 与 ObjC 对象交互时,可能会进行额外的引用计数操作和自动释放池活动。

当然,您不会总是为不需要或不需要的东西付费——并且记住 ObjC 类方法也比 C 函数有一些好处。因此,只需将 C 或 C++ 实现视为工具箱中的另一个工具即可。我发现随着复杂性和项目规模的增加它们非常有用,并且它们可以用来使您的程序更快。 2015 年就做你最不会后悔的事吧;)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Objective C 类方法与 C 函数 的相关文章

  • binary_log_types.h:没有这样的文件或目录

    我正在编译一个小型 mysql C 项目并且 遇到以下错误 C Program Files x86 MySQL MySQL Server 5 7 include mysql com h 22 30 fatal error binary lo
  • 动态选择和更新 LINQ 结果集中的列值

    我有一个场景 其中存在 LINQ 结果集 我使用了以下查询 var stockDetails from d in db BloodBanks where d bbUserName Session username ToString sele
  • 计算复杂数组的abs()值的最快方法

    我想计算 C 或 C 中复杂数组元素的绝对值 最简单的方法是 for int i 0 i lt N i b i cabs a i 但对于大向量来说 速度会很慢 有没有办法加快速度 例如使用并行化 语言可以是 C 或 C 鉴于所有循环迭代都是
  • 验证 iOS 应用程序时出现 com.apple.developer.linked-domains 问题

    当我在 Xcode 中使用 Organizer 验证我的项目时 出现以下错误 无效的代码签名权利 你的申请包的签名包含代码签名权利iOS 上不支持的 具体来说 值 for key com apple developer associated
  • 我要恢复我的记忆!我怎样才能真正处理一个控件?

    我正在制作一个应用程序 它创建大量的窗口控件 按钮和标签等 它们都是通过函数动态生成的 我遇到的问题是 当我删除控件并处置它们时 它们不会从内存中删除 void loadALoadOfStuff while tabControlToClea
  • 如何删除实体框架6中的多对多关系

    如果将项目连接为多对多关系 则从数据库中删除项目时会出现问题 我的数据库看起来像 Project lt JobInProject gt Job ProjectID JobInProjectID JobID ProjectID JobID 主
  • 修改正在运行的可执行文件的资源内容

    All 我将应用程序设置存储在资源中 当我的程序首次加载时 我使用 WinAPI 读取指定的资源 然后我解析检索到的字节数据 这对我来说完美无缺 现在假设用户更改了我的应用程序中的设置 他 她检查复选框控件 我想将更新的设置保存到我的资源中
  • 三种 System.Drawing 方法表现出缓慢的绘制或闪烁:解决方案?或其他选择?

    我正在通过 System Drawing 进行一些绘图 但遇到了一些问题 我将数据保存在队列中 并将该数据绘制 绘制 到三个图片框中 此方法填充图片框 然后滚动图形 所以不要在以前的绘图上绘制 并且逐渐看起来更混乱 我找到了两种绘制图表的解
  • 是否可以使用 UITableViewStylePlain 禁用 UITableView 中的浮动标题?

    我正在使用一个UITableView布局内容 页面 我使用表视图的标题来布局某些图像等 如果它们不浮动而是保持静态 就像样式设置为时那样 我更喜欢它UITableViewStyleGrouped 其他则使用UITableViewStyleG
  • 执行存储过程时 ExecuteNonQuery() 返回 -1

    我正在尝试在 Visual Studio 中执行存储过程 下面给出 CREATE PROCEDURE dbo addStudent stuName varchar 50 address varchar 100 tel varchar 15
  • 为什么 httpRuntime targetFramework="4.5" 禁止抓取 .ASPXAUTH cookie?

    当我的 web config 具有以下 httpRuntime 时 我的控制器无法获取 cookie ASPXAUTH 它似乎能够获取任何其他 cookie 无论带或不带句点前缀 如果我删除下面的行 它就可以正常工作
  • Nuget - 对象引用未设置为对象的实例

    我在 vs 2015 中遇到了 nuget 包管理器的问题 像Unity这样的一些包已经安装没有问题了 某些软件包 例如 EF 在安装时出现问题 像 Automapper 这样的一些软件包也有同样的问题 但是当我安装这个软件包的另一个版本时
  • C++:LPWSTR 在 cout 中打印为地址

    我有一个类型变量LPTSTR 我打印到std cout with lt lt 在 ANSI 系统中 不知道它是在哪里确定的 它工作得很好 它打印了字符串 现在 在 Unicode 系统中 我得到的是十六进制地址而不是字符串 那么 为什么LP
  • 使用非字符串作为字符串(而不是自动使用 ToString)时如何显示错误?

    建议的重复确实是一个类似的问题 然而 答案只涵盖一种选择 禁用 ToString 本身 还有其他可能的解决方案 例如让 Visual Studio 警告我 或者不调用 ToString 仔细阅读那里的答案 他认为is调用 只是解释说没有办法
  • C# 3.0 中自动属性和公共字段的区别

    我无法理解为什么 C 3 0 中存在自动实现的属性语言功能 当你说的时候有什么区别 public string FirstName than public string FirstName get set 因为它们在生成的 IL 代码 和机
  • NSCF 数组越界?

    我有一个相当简单的应用程序 使用 Core Data 和几个数组控制器 在 IB 中 除了 xcdatamodel 文件之外 没有它们的代码文件 当我运行应用程序时 我在日志中收到以下错误 应用程序仍然运行 但在转到 文件 gt 新文档 之
  • 是否可以编写一个在另一个 Windows 应用程序中选择文本时收到通知的 Windows 应用程序?

    我很好奇是否可以编写一个程序来监视我的文本选择 一种可能的用途是编写一个与编辑器 IDE 无关的代码格式化程序 应用程序 服务 P 启动并以某种方式挂接到窗口中 以便在任何窗口中选择文本时收到通知 启动其他一些应用程序 A 用户选择 A 中
  • char[length]初始化并处理

    我定义了一个字符数组 char d 6 如果我在以下方面有误 请纠正我 此时没有为变量分配内存d 现在我要初始化它 d aaaaa 这种初始化之后 就不需要释放内存了 它将自动完成 我怎么知道是否char 被初始化了吗 我正在寻找类似的模式
  • 使用 BASH 和 AWK 创建 HTML 表

    我在创建 html 表来显示文本文件中的统计信息时遇到问题 我确信有 100 种方法可以做得更好 但这里是 以下脚本中的注释显示了输出 bin bash function getapistats curl s http api exampl
  • C#:如何处理乱序 TCP 数据包?

    请有人解释一下如何处理乱序数据包 我使用原始套接字来捕获数据包 并在数据包到来时解析它们 但其中一些数据包的顺序错误 例如 ID 标志 16390 PSH ACK 16535 PSH ACK 16638 确认 16640 PSH ACK 1

随机推荐