针对旧版(iOS < 4)设备的通用应用程序(iPad+iPhone) - 有条件地采用协议?

发布于 2024-09-30 13:05:11 字数 514 浏览 0 评论 0 原文

我正在编写一个可以在 iPad 和 iPhone 上本地运行的通用应用程序。我还需要它针对较旧的设备(无法运行 4.0 的设备),因此 3.1 是必须的。

我已经将基础 SDK 设置为最新可用版本 (4.2),并将部署目标设置为 3.1。我正在进行大量的运行时检查,以便仅在正确的设备/版本上调用相应的方法。

我在 iPad 中使用的东西之一是 UISplitViewController。当分配 splitViewController 委托时,编译器会抛出警告,因为类接口没有显式采用 UISplitViewControllerDelegate 协议,而且我担心如果我声明它这样做,应用程序将在没有 UISplitViewController 的旧设备上崩溃/UISplitViewControllerDelegate.

抑制编译器警告的最佳方法是什么?我应该声明一个“空”UISplitViewControllerDelegate 吗?如果是这样,我可以在运行时有条件地做到这一点吗?或者我应该只让相应的类接口符合协议而不用担心旧设备?

最好的,

I'm writing an Universal App that will run natively on both iPad and iPhone. I also need it to be targeted to older devices (those that cannot run 4.0) so 3.1 is a must.

I have already set up the Base SDK to the latest available version (4.2), and the Deployment Target to 3.1. I am making lots of runtime checks in order to call the corresponding methods only on the right device/version.

One of the things I am making use of in the iPad is an UISplitViewController. When assigning the splitViewController delegate, the compiler throws a warning because the class interface isn't explicitly adopting the UISplitViewControllerDelegate protocol and I'm afraid that if I declare it to make it so, the App will crash on older devices where there is no UISplitViewController/UISplitViewControllerDelegate.

What is the best way to supress the compiler warning? Should I declare an 'empty' UISplitViewControllerDelegate? If so, can I make it conditionally at runtime? Or should I just make the corresponding class interface conform to the protocol and not worry about older devices?

Best,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只想待在家 2024-10-07 13:05:11

您可以使用简单的 C 强制转换来抑制警告:

foo.delegate = (id<UISplitViewControllerDelegate>)self;

You can suppress the warning with a simple C cast:

foo.delegate = (id<UISplitViewControllerDelegate>)self;
十级心震 2024-10-07 13:05:11

我还没有尝试过,但我很确定您可以无条件继续采用该协议,即使该类可能在没有该协议的旧运行时上使用。原因如下:

定义协议的所有信息都包含在声明 @protocol 的 .h 文件中。当您采用协议时,该协议声明会在 .h 文件中的某个位置导入(可能是通过 #import )。

当运行时需要了解有关协议的信息时,它会引用“协议对象”,您通常可以通过执行 @protocol(MyProtocolName) 在源代码中引用该对象。当遇到这样的协议引用时,编译器会创建此协议对象(在编译时),根据标题为 《Objective-C 编程语言》文档中的协议对象

因此,了解所有这些后,如果您采用协议并编写引用该协议对象的任何代码,则该协议对象将由编译器创建。即使您在较旧的设备上运行,编译器也应该为您创建该协议对象,所以我认为它不会导致崩溃。

希望这是有道理的。如果我有时间,我可以尝试一下,看看它在实践中是否有效,因为我的设备运行着从 3.1 到 4.2 的一系列 iOS 版本。

I haven't tried this, but I'm pretty sure you can just go ahead and adopt the protocol unconditionally, even if the class may be used on an older runtime that does not have the protocol. And here's why:

All the information for defining a protocol is contained in the .h file that declares the @protocol. When you adopt a protocol, that protocol declaration is imported at some point in your .h file (presumably by #import <UIKit/UIKit.h>).

When the runtime needs to know something about a protocol, it references a "Protocol Object", which you would normally reference in source code by doing @protocol(MyProtocolName). And the compiler creates this protocol object (at compile time) when such a protocol reference is encountered, according to the section titled Protocol Objects in The Objective-C Programming Language documentation.

So knowing all that, if you adopt a protocol and you write any code that references the protocol object, that protocol object will be created by the compiler. Even if you're running on an older device, the compiler should've created that protocol object for you, so I don't think it'll cause a crash.

Hope that makes sense. If I have some time I can try this out to see if it holds in practice because I have devices running a range of iOS versions from 3.1 to 4.2.

笛声青案梦长安 2024-10-07 13:05:11

如果您想使用打印并且应用程序在 4.2 之前运行,也会出现同样的问题。基本上它可以与此一起使用

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40200
// code for iOS 4.2++
@interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPrintInteractionControllerDelegate>{
#else
// code for iOS til 4.1
@interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>{
#endif

但是...看起来 InterfaceBuilder 无法处理这个问题。此条件定义之后的所有出口定义都在 IB 中消失。

那么还有更好的解决方案吗?

问候
格尔德

Same problem if you want to use printing and stil have the app runnig before 4.2. Basically it works with this

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40200
// code for iOS 4.2++
@interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPrintInteractionControllerDelegate>{
#else
// code for iOS til 4.1
@interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>{
#endif

But... It looks like the InterfaceBuilder can't handle this. All outlets defines after this conditional definition ar gone in IB.

So any better solution?

Regards
Gerd

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文