【问题标题】:swift, write code for ios 7 and 8swift,为 ios 7 和 8 编写代码
【发布时间】:2014-08-07 00:56:21
【问题描述】:

我有一个使用 Swift 编写的测试应用程序,我想针对 iOS 7。但是启用我需要添加的本地通知

application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound 
    | UIUserNotificationType.Alert 
    | UIUserNotificationType.Badge, 
    categories: nil))

但是这个调用在 iOS 7 中不可用,所以我添加了

var version:NSString = UIDevice.currentDevice().systemVersion as NSString;
if  version.doubleValue >= 8 {
    // ios 8 code
}

ios 8 代码块仅在 iOS 8 下运行(已测试),但在 iOS 7 中运行应用程序时,我仍然得到 ​​p>

dyld:未找到符号:_OBJC_CLASS_$_UIUserNotificationSettings 引用自:/var/mobile/Applications/AC73969D-1A4C-45AC-99CA-0B3982C1EE36/Timely.app/Timely 预期在:/System/Library/Frameworks/UIKit.framework/UIKit 在 /var/mobile/Applications/AC73969D-1A4C-45AC-99CA-0B3982C1EE36/Timely.app/Timely

我认为这是因为二进制文件包含 iOS 7 中不存在的 api 符号,但我该如何解决这个问题?

【问题讨论】:

  • 什么时候看到这个错误?
  • 当启动应用程序时,但我在应用程序委托中有这个块,代码在 ios 8 中工作并且没有错误删除 ios 7 中的块
  • 您正在使用正确的 sdk 进行编译,不是吗?所以即使你在 iOS7 设备上启动这个应用,你也应该用最新的基础 sdk 编译它……
  • 如果您将项目的目标更改为 iOS7 会发生什么?我猜(目前至少在测试版中)当你编译应用程序时,它会继续并将所有 iOS8 符号放入其中,当涉及到dyld 将 iOS7 上的所有内容链接在一起时,它会发现一大堆它不理解的 iOS8 主义。
  • afaik 如果部署目标不是 ios 7 或更低版本,您将无法在 ios 7 上进行部署

标签: ios swift


【解决方案1】:

很遗憾,我认为您遇到了当前限制,请参阅此

What is the Swift preprocessor equivalent to iOS version check comparison?

解决此问题的唯一方法是添加一个 Objective-C 文件,然后使用 #if 宏并创建两个从 Swift 调用的辅助函数(一个用于 iOS8,一个用于 iOS7)。我希望这会在某个时候得到解决。

【讨论】:

  • #if 不适合这里。系统版本不是在编译时决定的。 ios7 和 ios8 可以使用相同的二进制文件
  • 这确实有效,通过检查 objc 中的 UIDevice 系统版本,应用程序没有抱怨未知符号,可惜这是一个 hack
  • 只是现在。我很确定这是一个错误。您可能需要提交雷达。
  • 您不需要#if,因为正如 Bryan Chen 所说,问题在于运行时,而不是编译时间。这只能通过将代码转移到 Objective-C 来“起作用”,我们已经知道它没有这个问题。 (Objective-C 编译器正确弱链接符号,这些符号仅在比部署目标更高的版本中可用。)
【解决方案2】:

在 Beta6 中,部分(全部?)链接问题似乎已得到修复。与 UIAlertAction 和 UIAlertController 链接的应用程序过去无法在 7.1 上启动,但现在将启动。您仍然无法在 7.1 中使用它们,但您可以测试 iOS 版本并使用较旧的对象。

【讨论】:

    【解决方案3】:

    我遇到了类似的问题,所以对于遇到此问题的任何人,这是另一种可能的解决方案:

    如果您转到 Target > General > Linked Frameworks and Libraries,您应该会看到 UIKit(如果没有,请添加它)。确保它旁边显示“可选”而不是“必需”...

    【讨论】:

      【解决方案4】:

      这是一种肮脏的技巧,但它对我有用:

      if(UIApplication.sharedApplication().respondsToSelector("isRegisteredForRemoteNotifications")){ println("is iOS8") }
      

      【讨论】:

        【解决方案5】:

        Prasath有一个very good answer,但它是用Objective-C写的,
        所以我在 swift 中写了类似的东西:

        (在 Xcode 6 中测试)

        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
           // ...
        
           // Set Notification
        
           if UIApplication.sharedApplication().respondsToSelector(Selector("registerUserNotificationSettings:")) {
        
              // Notifications for iOS 8
              let notificationSettings = UIUserNotificationSettings(forTypes: .Alert | .Sound, categories: nil)
              UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
           }
           else {
              // Notifications for iOS < 8
              UIApplication.sharedApplication().registerForRemoteNotificationTypes(.Alert | .Sound)
           }
        
           // ...
        
           return true
        }
        

        希望有帮助

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-19
          相关资源
          最近更新 更多