Je reçois
yld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings
et voici la fonction qui cause l'erreur lorsque l'application s'exécute sur un périphérique iOS7 et sans même appeler la fonction dans le code.
func reigsterForRemoteUserNotifications(notificationTypes: UIUserNotificationType, categories: NSSet) { let userNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: categories) (UIApplication.sharedApplication()).registerUserNotificationSettings(userNotificationSettings) UIApplication.sharedApplication().registerForRemoteNotifications() }
Je ne veux pas du tout que cette méthode soit accessible lors de l'exécution sur un périphérique iOS7. Je ne veux pas de chèque de sélection à l'intérieur car cela signifie que la méthode est disponible pour commencer.
Ce que je veux, c'est un paramètre de configuration de construction permettant de vérifier la version: je ne trouve pas le moyen d'écrire une macro de préprocesseur équivalente à Swift pour rechercher la version iOS appropriée et de négliger les nouvelles fonctions de bibliothèque iOS 8 non déclarées.
#if giOS8OrGreater
// declare the functions that are iOS 8 specific
#else
// declare the functions that are iOS 7 specific
#endif
Dans la documentation, Apple suggère des fonctions et des génériques pour remplacer des macros complexes, mais dans ce cas, j'ai besoin d'un contrôle de précompilation de la configuration de construction pour éviter le traitement de fonctions non déclarées. Aucune suggestion.
Les autres réponses ne mentionnent pas les moyens appropriés de vérifier la version du système. Vous ne devez absolument jamais utiliser: Device.systemVersion
Vous ne devez pas créer de macros personnalisées pour vérifier les numéros de version, et vous ne devez pas creuser au-delà des bibliothèques définies spécifiquement par Apple pour cette tâche.
Il y a un excellent article détaillant ceci ici .
Notez que Swift 2.0 vous permet de vérifier directement si un numéro de version de système d'exploitation est disponible via:
if #available(iOS 10.0, *) {
// modern code
} else {
// Fallback on earlier versions
}
Avant Swift 2.0, l'approche recommandée était via les macros système fournies:
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_0) {
// do stuff for iOS 9 and newer
} else {
// do stuff for older versions than iOS 9
}
ou via:
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) {
// modern code
}
Pour tout ce qui manque au-delà des macros du système.
Toute autre approche a été minimisée et considérée comme non fiable et non recommandée par Apple. Il y a en fait une approche qui va casser dans iOS 10.
Notez que si vous avez besoin de fonctionnalités similaires à une macro dans une vérification et que vous souhaitez utiliser #available
, vous pouvez utiliser @available
défini dans cet article en tant que tel:
@available(iOS 7, *)
func iOS7Work() {
// do stuff
if #available(iOS 8, *) {
iOS8Work()
}
}
@available(iOS 8, *)
func iOS8Work() {
// do stuff
if #available(iOS 9, *) {
iOS9Work()
}
}
@available(iOS 9, *)
func iOS9Work() {
// do stuff
}
Pour plus d'informations sur les attributs dans Swift, vous pouvez vous référer à documentation Apple .
Dans Constants.Swift
:
Swift 1:
let Device = UIDevice.currentDevice()
private let iosVersion = NSString(string: Device.systemVersion).doubleValue
Swift 2:
let Device = UIDevice.currentDevice()
private let iosVersion = Double(Device.systemVersion) ?? 0
let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8
Puis dans d'autres fichiers
if iOS8
{
}
else
{
}
Mise à jour: Ceci est corrigé dans Xcode 6 beta 6 (build 6A280e)
Voici une solution de contournement (peut-être pas si excellente): associez explicitement le lien UIKit à un état faible (je sais que les déclarations import
sont supposées renvoyer déjà à des frameworks, mais nous le faisons explicitement quand même).
Cela peut entraîner une faible liaison de tous les UIKit, ce qui peut affecter les performances. Pas certain.
En Objective-C, même avec Obligatoire, le compilateur a automatiquement lié les symboles dont la disponibilité était supérieure à la cible de déploiement, et a laissé les autres fortement liés. Je ne sais pas pourquoi cela ne fonctionne pas avec Swift.
var systemVersion = UIDevice.currentDevice (). systemVersion
Selon Apple, il n'y a pas d'appels de préprocesseur dans Swift, mais le code Swift peut être compilé sous condition en fonction de l'évaluation des configurations de construction dans deux fonctions. Pour l'instant, nous avons os()
pour un choix d'OSX ou iOS et Arch()
pour un choix de x86_64, arm, arm64 ou i386. Donc, vous pouvez évaluer #if os(iOS)
, mais pas #if os(iOS8)
(bien que cela semble une bonne idée pour les versions ultérieures de Swift).
Vous pouvez vérifier la version iOS par -
let iosVersion = UIDevice.currentDevice().systemVersion
Et comparez-le avec NSStringCompareOptions.NumericSearch
switch iosVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)
{
case .OrderedSame, .OrderedDescending:
//iOS>=8.0.0
return LAContext()
case .OrderedAscending:
//iOS<8.0.0
return nil
}
Vous pouvez également utiliser les nouvelles API NSProcessInfo, mais elles ne sont pas disponibles pour iOS 7.
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) {
//iOS>=8.0.0
}
Vous pouvez voir plus de détails ici . J'espère que cela résoudra votre question.