iPhone 在通用应用程序中检查运行时的常量

发布于 2024-08-30 17:21:53 字数 961 浏览 3 评论 0原文

我正在制作一个通用的 iPad/iPhone 应用程序,它可以使用 iPad 的 VGA 输出连接器将应用程序的内容镜像到外部屏幕上。不过iPhone不具备这个功能。给出以下代码,

#ifdef UI_USER_INTERFACE_IDIOM  
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    NSLog(@"this code should not execute on iphone");
[[NSNotificationCenter defaultCenter] addObserver:self
         selector:@selector(screenInfoNotificationReceieved:) 
          name:UIScreenDidConnectNotification
           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
         selector:@selector(screenInfoNotificationReceieved:) 
          name:UIScreenDidDisconnectNotification
           object:nil];
}
#endif

我在启动时在手机上收到此错误(在 ipad 中工作正常) “dyld:未找到符号:_UIScreenDidConnectNotification”

大概是因为 UIScreenDidConnectNotification 在 3.13 中尚不存在。我如何在运行时检查这一点?

更新 添加了 ifdef 语句来检查 ipad 接口,但得到相同的结果!

更新添加了 NSLog 语句以确保 if 语句内的代码未被调用。崩溃似乎发生在执行任何其他代码之前......

I'm making a universal iPad/iPhone app which can use the iPad's VGA out connector to mirror the content of the app on an external screen. However, the iPhone does not have this functionality. given the following code,

#ifdef UI_USER_INTERFACE_IDIOM  
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    NSLog(@"this code should not execute on iphone");
[[NSNotificationCenter defaultCenter] addObserver:self
         selector:@selector(screenInfoNotificationReceieved:) 
          name:UIScreenDidConnectNotification
           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
         selector:@selector(screenInfoNotificationReceieved:) 
          name:UIScreenDidDisconnectNotification
           object:nil];
}
#endif

I get this error on the phone at launch (works fine in ipad)
"dyld: Symbol not found: _UIScreenDidConnectNotification"

presumably because UIScreenDidConnectNotification doesnt' exist yet in 3.13. How do I check for this at runtime?

UPDATED added ifdef statements to check for ipad interface but getting the same result!

UPDATED added NSLog statement to make sure the code inside the if statement is not being called. The crash seems to occur before any other code is executed...

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

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

发布评论

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

评论(4

┈┾☆殇 2024-09-06 17:21:53

尝试弱链接 UIKit。添加到其他链接标志中:

-all_load -ObjC -weak_framework UIKit

如果您的目标是 3.1 之前的设备,但引用仅存在于 3.2 中的类,则不能通过符号引用它们,必须使用 NSClassFromString。但在某些情况下这是不可能的,例如,如果您对这样的类进行子类化(例如 UIPopoverController)。在这些情况下,你必须弱链接 UIKit。当您弱链接框架时,动态加载器会尝试在启动时解析所有符号,如果失败,则将其设置为 NULL。

我猜测常量 UIScreenDidConnectNotification 未标记(错误),因此您需要使用相同的解决方法。

弱链接有一个缺点。由于它必须在启动时动态地执行此操作,因此启动时间会受到影响。您必须测试它是否对您来说太慢。

弱链接框架的另一种方法是:在目标上执行“获取信息”,然后在“常规”选项卡下,您将看到框架列表。将 UIKit 的类型更改为 Weak。

顺便说一句,使用 #ifdef 进行检查不起作用,因为 #ifdef 是编译时构造,因此 UI_USER_INTERFACE_IDIOM 将始终被定义,因为您正在使用 3.2 SDK 进行构建

Try weak link UIKit. Add into your other link flags:

-all_load -ObjC -weak_framework UIKit

If you target pre-3.1 devices but refer to a class which only exists in 3.2, you can't refer to them by symbol, you have to use NSClassFromString. But there are cases where this isn't possible, e.g. if you subclass such a class (say UIPopoverController). In those cases you have to weak-link UIKit. When you weak-link a framework, the dynamic loader attempts to resolve all the symbols on startup, if it fails, it's set to NULL.

I'm guessing the constant UIScreenDidConnectNotification isn't tagged (bug), so you need to use the same workaround.

There is a downside to weak-linking. Since it has to do this upon startup, dynamically, startup time takes a hit. You'll have to test if it is too slow for you.

Another way to weak link a frame is: do "Get Info" on your target and under the General tab, you will see the list of frameworks. Change the type for UIKit to Weak.

BTW, using a #ifdef to check doesn't work, because #ifdef are compile-time constructs, so UI_USER_INTERFACE_IDIOM will always be defined because you are building using the 3.2 SDK

路还长,别太狂 2024-09-06 17:21:53

从埃尔弗雷德对相关问题的回答: 创建 iPhone 通用二进制文件时如何测试常量是否存在

if (NULL != &UIBackgroundTaskInvalid) {
   //do multitasking stuff here
} else {
   // don't do multitasking stuff here.
}

From Elfred's answer to related question: How to test for the existance of a constant when creating a iPhone universal binary

if (NULL != &UIBackgroundTaskInvalid) {
   //do multitasking stuff here
} else {
   // don't do multitasking stuff here.
}
总攻大人 2024-09-06 17:21:53

按照 http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html" rel="nofollow noreferrer">http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html 中的“以编程方式确定设备”部分操作/iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html

添加

#ifndef __IPHONE_3_2 // if iPhoneOS is 3.2 or greater then __IPHONE_3_2 will be defined
  typedef enum { // provided by noblemaster ]:-|
    UIUserInterfaceIdiomPhone, // iPhone and iPod touch style UI
    UIUserInterfaceIdiomPad, // iPad style UI
  } UIUserInterfaceIdiom;
  #define UI_USER_INTERFACE_IDIOM() (([[UIDevice currentDevice].model rangeOfString:@"iPad"].location != NSNotFound) ? UIUserInterfaceIdiomPad : UIUserInterfaceIdiomPhone)
#endif // ifndef __IPHONE_3_2 

在评论部分。

Follow the "Programmatically Determining Device" section at http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html

plus

#ifndef __IPHONE_3_2 // if iPhoneOS is 3.2 or greater then __IPHONE_3_2 will be defined
  typedef enum { // provided by noblemaster ]:-|
    UIUserInterfaceIdiomPhone, // iPhone and iPod touch style UI
    UIUserInterfaceIdiomPad, // iPad style UI
  } UIUserInterfaceIdiom;
  #define UI_USER_INTERFACE_IDIOM() (([[UIDevice currentDevice].model rangeOfString:@"iPad"].location != NSNotFound) ? UIUserInterfaceIdiomPad : UIUserInterfaceIdiomPhone)
#endif // ifndef __IPHONE_3_2 

in the comments section.

溺渁∝ 2024-09-06 17:21:53

弱链接框架的另一种方法是:在目标上执行“获取信息”,然后在“常规”选项卡下,您将看到框架列表。将 UIKit 的类型更改为 Weak。

这对我解决了运行时 iPhone 上的“符号未找到:_UIScreenDidConnectNotification”问题。

Another way to weak link a frame is: do "Get Info" on your target and under the General tab, you will see the list of frameworks. Change the type for UIKit to Weak.

That worked for me for the issue "Symbol not found: _UIScreenDidConnectNotification" on iPhone at runtime.

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