2 Replies
      Latest reply on Sep 21, 2015 6:07 AM by OOPer
      OOPer Level 8 Level 8 (5,425 points)

        When I was writing a compatibility wrapper for AddressBook and Contacts frameworks, I found this code does not work in iOS 7:

        import Foundation
        import AddressBook
        import AddressBookUI
        import Contacts
        import ContactsUI
        private var k2Key: [ABPropertyID: String] = [
            ://...
        ]
        private func setupConstants() {
            //...
            if #available(iOS 8.0, *) {
                // Alternate birthday
                //@availability(iOS, introduced=8.0)
                k2Key[kABPersonAlternateBirthdayProperty] = MyContactNonGregorianBirthdayKey
            }
            //...
        }
        
        

        As shown in the comment, the constant kABPersonAlternateBirthdayProperty is introduced in iOS 8.0, so I enclosed the code with #available check.

        But it causes a runtime error, when run on iOS 7 device:

        dyld: Symbol not found: _kABPersonAlternateBirthdayProperty
          Referenced from: /var/mobile/Applications/3F5FB593-AC7B-4F5A-9563-66A5949769D4/QuickContacts.app/QuickContacts
          Expected in: /System/Library/Frameworks/AddressBook.framework/AddressBook
         in /var/mobile/Applications/3F5FB593-AC7B-4F5A-9563-66A5949769D4/QuickContacts.app/QuickContacts
        
        

         

        How do you check availability of a constant and use it safely?

        • Re: Constant Availability Check in Swift
          eskimo Apple Staff Apple Staff (12,285 points)

          It looks like the new AB_DEPRECATED macro, which decorates all the Address Book framework, does not take into account when the symbol was * introduced.  I’d call that a bug and I recommend that you file it as such.  Please post your bug number, just for the record.

          As to a workaround, you may be able to cobble something together with a bridging header hack but if I were in your shoes I’d do one of two things:

          • access the symbolic dynamically

          • bounce over to Objective-C and, in your Objective-C code, redeclare the symbol with the correct availability settings

          Share and Enjoy

          Quinn "The Eskimo!"
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: Constant Availability Check in Swift
              OOPer Level 8 Level 8 (5,425 points)

              Thanks, eskimo.

               

              • access the symbolic dynamically

              This is what I use now:

                  let RTLD_DEFAULT = UnsafeMutablePointer<Void>(bitPattern: -2)
                  if dlsym(RTLD_DEFAULT, "kABPersonAlternateBirthdayProperty") != nil {
                      let kAddress = dlsym(RTLD_DEFAULT, "kABPersonAlternateBirthdayProperty")
                      let kABPersonAlternateBirthdayProperty = UnsafePointer<ABPropertyID>(kAddress).memory
                      //...code using kABPersonAlternateBirthdayProperty
                  }
              

               

              I'll report bug number later.