gpt4 book ai didi

objective-c - 覆盖Objective-C框架方法是否是一个好主意?

转载 作者:可可西里 更新时间:2023-11-01 05:42:19 24 4
gpt4 key购买 nike

ObjC具有一种非常独特的重写方法。具体来说,您可以覆盖OSX自己框架中的功能。通过“类别”或“模糊”。您甚至可以覆盖仅在内部使用的“埋藏”功能。

有人可以给我提供一个有充分理由这样做的例子吗?您会在已发布的商业软件中使用某些东西,而不仅仅是一些内部使用的黑客工具?

例如,也许您想改进某些内置方法,或者您想修复的框架方法中有一个错误。

另外,您能否解释一下为什么最好使用ObjC中的功能而不是C++ / Java等中的功能。我的意思是,我听说过可以加载C库的功能,但可以用以前加载的同名功能替换某些函数。 ObjC如何更好地修改库行为呢?

最佳答案

如果您将问题从单纯的讨论扩展到实际的库修改,那么我可以想到一些有用的示例。

从iOS 5开始,NSURLConnection提供了 sendAsynchronousRequest:queue:completionHandler: ,这是一种块(/关闭)驱动的方式,可从可通过URL识别的任何资源(本地或远程)执行异步加载。这是一种能够继续进行的非常有用的方法,因为它使您的代码比传统的委托替代方法更干净,更小,并且更有可能使代码的相关部分彼此接近。

iOS 4中未提供该方法。因此,在我的项目中完成的工作是,在启动应用程序时(通过适当的+ (void)load),我检查该方法是否已定义。如果没有,我会在类上修补它的实现。此后,程序的其他所有部分都可以写入iOS 5规范,而无需执行任何版本或可用性检查,就好像我只针对iOS 5,除了它也可以在iOS 4上运行。

在Java或C++中,我猜想通过创建自己的类来发布URL连接,并在每次调用时执行运行时检查,可以实现相同的目的。这是一个更糟糕的解决方案,因为要退出它更困难。这样一来,如果我决定只支持iOS 5,我只需删除添加了sendAsynchronousRequest:...实现的源文件。没有其他改变。

至于方法混乱,我看到的唯一建议是,有人要更改现有类的功能,而又无权访问创建该类的代码。因此,您通常是在谈论通过对代码实现的假设来尝试从外部修改逻辑上不透明的代码。我不会真的支持任何语言的想法。我猜想它会在Objective-C中得到更多推荐,因为Apple更倾向于使事物变得不透明(例如,每个想要在iOS 3.1之前显示自定义相机视图的应用程序,每个想要对相机输入执行自定义处理的应用程序到iOS 4.0等),而不是因为这在Objective-C中是个好主意。不是。

编辑:因此,在进一步的说明中-我无法发布完整的代码,因为我将其编写为工作的一部分,但是我有一个名为NSURLConnectionAsyncForiOS4的类,带有sendAsynchronousRequest:queue:completionHandler:的实现。该实现实际上很简单,只需将操作分派到指定的队列,该队列就通过旧的sendSynchronousRequest:...接口进行同步加载,然后将结果发布到处理程序中。

该类具有一个+ (void)load,这是您添加到一个类的类方法,该类方法将在该类被加载到内存后立即发出,有效地作为元类的全局构造函数,并带有所有常见的警告。

在我的+load中,我直接通过其C接口使用Objective-C运行时检查sendAsynchronousRequest:...上是否定义了NSURLConnection。如果不是,那么我将实现添加到NSURLConnection,因此从此开始对其进行定义。显然,这并没有麻烦-我没有调整任何东西的现有实现,只是添加了用户提供的某些东西的实现(如果无法使用Apple的实现)。相关的运行时调用为objc_getClassclass_getClassMethodclass_addMethod

在其余的代码中,每当我想执行异步URL连接时,我都会写例如

[NSURLConnection sendAsynchronousRequest:request
queue:[self anyBackgroundOperationQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *blockError)
{
if(blockError)
{
// oh dear; was it fatal?
}

if(data)
{
// hooray! You know, unless this was an HTTP request, in
// which case I should check the response code, etc.
}

/* etc */
}

因此,我的其余代码只是写到iOS 5 API中,既不知道也不在乎我是否在其他地方安装了垫片,以提供iOS 5的一个微观部分在iOS 4上的更改。而且,正如我所说,当我停止时支持iOS 4我将只从项目中删除填充程序,其余所有代码将继续不为所知或关心。

我有类似的代码来提供 NSJSONSerialization的替代部分实现(它在运行时动态创建一个新类并将方法复制到该类);您需要进行的一项调整是,在链接时,链接器将解决对其他位置的 NSJSONSerialization的引用,而这并不是您真正想要的。因此,我在预编译的标头中向 #define添加了 NSJSONSerialization的快速 NSClassFromString(@"NSJSONSerialization")。就寻找一种暂时保持iOS 4支持的方式,而只是将项目的其余部分编写为iOS 5标准而言,这在功能上不那么整洁,但采取了类似的行动。

关于objective-c - 覆盖Objective-C框架方法是否是一个好主意?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9844309/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com