gpt4 book ai didi

objective-c - 如何动态类型转换对象以支持应用程序的 ScriptingBridge 头文件的不同版本?

转载 作者:搜寻专家 更新时间:2023-10-30 20:09:22 25 4
gpt4 key购买 nike

目前我正在尝试通过 ScriptingBridge 实现对 iTunes 的多个版本的支持。

例如,属性 playerPosition 的方法签名从 (10.7) 更改

@property NSInteger playerPosition;  // the player’s position within the currently playing track in seconds.

至 (11.0.5)

@property double playerPosition;  // the player’s position within the currently playing track in seconds

对于我的应用程序中最新的头文件和较旧的 iTunes 版本,此属性的返回值将始终为 3。反之亦然。

所以我继续创建三个不同的 iTunes 头文件,11.0.5、10.7 和 10.3.1,通过

sdef /path/to/application.app | sdp -fh --basename applicationName

对于每个版本的 iTunes,我都修改了基本名称以包含版本,例如iTunes_11_0_5.h。这导致头文件中的接口(interface)以其特定版本号为前缀。我的目标是/曾经使用正确版本的接口(interface)对我要使用的对象进行类型转换。

iTunes 的路径是通过 NSWorkspace 方法获取的,然后我从中创建一个 NSBundle 并从 infoDictionary 中提取 CFBundleVersion

这三个不同的版本(11.0.5、10.7、10.3.1)也被声明为常量,我通过它与用户的 iTunes 版本进行比较

[kiTunes_11_0_5 compare:versionInstalled options:NSNumericSearch]

然后我检查每个结果是否等于 NSOrderedSame,这样我就知道用户安装了哪个版本的 iTunes。

用 if 语句实现这个有点失控,因为我需要在类里面的许多不同地方进行这些类型转换,然后我开始意识到这将导致大量重复代码并进行修改并思考这个问题以找到一个不同的解决方案,一个更“最佳实践”的解决方案。

一般来说,我需要对我使用的对象进行动态类型转换,但我根本找不到不会导致大量重复代码的解决方案。

编辑

if ([kiTunes_11_0_5 compare:_versionString options:NSNumericSearch] == NSOrderedSame) {
NSLog(@"%@, %@", kiTunes_11_0_5, _versionString);
playerPosition = [(iTunes_11_0_5_Application*)_iTunes playerPosition];
duration = [(iTunes_11_0_5_Track*)_currentTrack duration];
finish = [(iTunes_11_0_5_Track*)_currentTrack finish];
} else if [... and so on for each version to test and cast]

最佳答案

[所有代码直接输入答案。]

您可以使用类别代理 或辅助类来解决这个问题,这是后者的一种可能设计的草图。

首先创建一个辅助类,它采用 iTunes 对象和版本字符串的实例。还要避免进行重复的字符串比较,在类设置中进行一次比较。您没有提供 iTunes 应用程序对象的类型,因此我们将随机调用它 ITunesAppObj - 替换为正确的类型:

typedef enum { kEnumiTunes_11_0_5, ... } XYZiTunesVersion;

@implementation XYZiTunesHelper
{
ITunesAppObj *iTunes;
XYZiTunesVersion version;
}

- (id) initWith:(ITunesAppObj *)_iTunes version:(NSString *)_version
{
self = [super self];
if (self)
{
iTunes = _iTunes;
if ([kiTunes_11_0_5 compare:_version options:NSNumericSearch] == NSOrderedSame)
version = kEnumiTunes_11_0_5;
else ...
}
return self;
}

现在为每个在版本之间改变类型的项目添加一个项目到这个类,用你选择的任何“通用”类型声明它。例如。对于 playerPosition 这可能是:

@interface XYZiTunesHelper : NSObject

@property double playerPosition;
...

@end


@implementation XYZiTunesHelper

// implement getter for playerPosition
- (double) playerPosition
{
switch (version)
{
case kEnumiTunes_11_0_5:
return [(iTunes_11_0_5_Application*)_iTunes playerPosition];

// other cases - by using an enum it is both fast and the
// compiler will check you cover all cases
}
}

// now implement the setter...

对轨道类型做类似的事情。您的代码片段将变为:

XYZiTunesHelper *_iTunesHelper = [[XYZiTunesHelper alloc] init:_iTunes
v ersion:_versionString];

...

playerPosition = [_iTunesHelper playerPosition];
duration = [_currentTrackHelper duration];
finish = [_currentTrackHelper finish];

以上是您请求的动态 - 在每次调用时都有一个开关来调用适当的版本。您当然可以使 XYZiTunesHelper 类抽象(或接口(interface)或协议(protocol)),并为每个 iTunes 版本编写三个实现,然后进行一次测试并选择适当的实现。这种方法更“面向对象”,但它确实意味着 playerPosition 的各种实现并不在一起。在这个特殊情况下,选择您觉得最舒服的样式。

HTH

关于objective-c - 如何动态类型转换对象以支持应用程序的 ScriptingBridge 头文件的不同版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18878748/

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