web-dev-qa-db-fra.com

apparenceWhenContainedIn in Swift

J'essaie de convertir mon application dans la langue Swift.

J'ai cette ligne de code:

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
                     setTitleTextAttributes:textDictionary
                                   forState:UIControlStateNormal];

Comment le convertir en Swift?

Dans documentation d'Apple , cette méthode n'existe pas.

124
AlexZd

Mise à jour pour iOS 9:

Si vous ciblez iOS 9+ (à partir de Xcode 7 b1), il existe une nouvelle méthode dans le protocole UIAppearance qui n'utilise pas de variables:

static func appearanceWhenContainedInInstancesOfClasses(containerTypes: [AnyObject.Type]) -> Self

Qui peut être utilisé comme suit:

UITextField.appearanceWhenContainedInInstancesOfClasses([MyViewController.self]).keyboardAppearance = .Light

Si vous devez toujours prendre en charge iOS 8 ou une version antérieure, utilisez la réponse originale suivante à cette question.

Pour iOS 8 et 7:

Ces méthodes ne sont pas disponibles pour Swift car les méthodes Obj-C varargs ne sont pas compatibles avec Swift (voir http: //www.openradar. moi/17302764 ).

J'ai écrit une solution de contournement non variadique qui fonctionne dans Swift (j'ai répété la même méthode pour UIBarItem, qui ne descend pas de UIView.)):

// UIAppearance+Swift.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (UIViewAppearance_Swift)
// appearanceWhenContainedIn: is not available in Swift. This fixes that.
+ (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass;
@end
NS_ASSUME_NONNULL_END

-

// UIAppearance+Swift.m
#import "UIAppearance+Swift.h"
@implementation UIView (UIViewAppearance_Swift)
+ (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass {
    return [self appearanceWhenContainedIn:containerClass, nil];
}
@end

Assurez-vous juste de #import "UIAppearance+Swift.h" dans votre en-tête de pontage.

Ensuite, pour appeler de Swift (par exemple):

# Swift 2.x:
UITextField.my_appearanceWhenContainedIn(MyViewController.self).keyboardAppearance = .Light

# Swift 3.x:
UITextField.my_appearanceWhenContained(in: MyViewController.self).keyboardAppearance = .light
229
Alex Pretzlav

ios 10 Swift 3

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Kapat"
31
user5681291

Pour iOS 8 et 7:

J'utilise une catégorie basée sur la réponse d'Alex pour spécifier plusieurs conteneurs. Ceci est une solution de contournement jusqu'au Apple supporte officiellement appearanceWhenContainedIn dans Swift.

UIAppearance + Swift.h

@interface UIView (UIAppearance_Swift)
/// @param containers An array of Class<UIAppearanceContainer>
+ (instancetype)appearanceWhenContainedWithin: (NSArray *)containers;
@end

UIAppearance + Swift.m

@implementation UIView (UIAppearance_Swift)

+ (instancetype)appearanceWhenContainedWithin: (NSArray *)containers
{
    NSUInteger count = containers.count;
    NSAssert(count <= 10, @"The count of containers greater than 10 is not supported.");

    return [self appearanceWhenContainedIn:
            count > 0 ? containers[0] : nil,
            count > 1 ? containers[1] : nil,
            count > 2 ? containers[2] : nil,
            count > 3 ? containers[3] : nil,
            count > 4 ? containers[4] : nil,
            count > 5 ? containers[5] : nil,
            count > 6 ? containers[6] : nil,
            count > 7 ? containers[7] : nil,
            count > 8 ? containers[8] : nil,
            count > 9 ? containers[9] : nil,
            nil];
}
@end

Puis ajouter #import "UIAppearance+Swift.h" à votre en-tête de pontage.

À utiliser depuis Swift :

TextField.appearanceWhenContainedWithin([MyViewController.self, TableViewController.self]).keyboardAppearance = .Light

C'était bien si je pouvais trouver un moyen d'utiliser CVarArgType , mais je n'ai trouvé aucune solution propre.

14
Yoichi Tagaya

Voici une solution de contournement moins laide, mais toujours laide, inspirée de @tdun.

  1. Créez une classe pour contenir votre apparence Objective-C. Aux fins de cet exemple, appelons-le AppearanceBridger.
  2. Ajoutez cette classe à votre en-tête de pontage. Si vous n'avez pas d'en-tête de pontage, en créer un .
  3. Créez une méthode de classe dans AppearanceBridger nommée +(void)setAppearance et insérez le code d'apparence d'Objective-C dans cette méthode. Par exemple:

+ (void)setAppearance {
    [[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}
  1. Dans votre code Swift où vous définissez l'apparence, appelez AppearanceBridger.setAppearance()] _ et vous devriez être prêt à partir!

J'espère que cela fonctionne bien pour les personnes qui le voient.

12
Baub

Cela peut être étendu à toute classe conforme au protocole UIAppearance - pas seulement à UIViews. Alors, voici une version plus générique:

IAppearance + Swift.h

#import <UIKit/UIKit.h>

@interface NSObject (UIAppearance_Swift)

+ (instancetype)appearanceWhenContainedWithin:(Class<UIAppearanceContainer>)containerClass;

@end

IAppearance + Swift.m

#import "UIAppearance+Swift.h"

@implementation NSObject (UIAppearance_Swift)

+ (instancetype)appearanceWhenContainedWithin:(Class<UIAppearanceContainer>)containerClass {
    if ([self conformsToProtocol:@protocol(UIAppearance)]) {
        return [(id<UIAppearance>)self appearanceWhenContainedIn:containerClass, nil];
    }
    return nil;
}

@end
4
Eddie K

Voici une solution de contournement laide que j'ai utilisé ....

Créez simplement une classe tactile Objective-C Cocoa (UIViewController), nommée comme vous le souhaitez.

J'ai nommé le mien WorkaroundViewController...

Maintenant dans (WorkaroundViewController.m):

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

Exécutez le code d'apparence d'Objective-C pour .appearanceWhenContainedIn() (voici mon exemple):

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Avenir-Light" size:16.0f]}];

Puis créez un en-tête de pontage pour votre Swift, puis initialisez votre ViewController Objective-C dans votre Swift, comme ceci ( encore, juste mon exemple):

var work : WorkaroundViewController = WorkaroundViewController()

Alors vous avez fini! Faites-moi savoir si cela fonctionne pour vous ... Comme je l'ai dit, c'est moche, mais ça marche!

4
tcd

J'ai créé un dépôt pour vous qui voulez utiliser CocoaPods:

  1. Ajoutez ceci dans votre Podfile:

    pod 'UIViewAppearanceSwift'
    
  2. Importer dans votre classe:

    import UIViewAppearanceSwift
    
    func layout() {
        UINavigationBar.appearanceWhenContainedWithin(MFMailComposeViewController.self).barStyle = .Black
        UIBarButtonItem.appearanceWhenContainedWithin(UISearchBar.self).setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(15)], forState: UIControlState.Normal)
    }
    
  3. Référence: https://github.com/levantAJ/UIViewAppearanceSwift

3
Tai Le

Swift 4: iOS 9 +

UIProgressView.appearance(whenContainedInInstancesOf: [LNPopupBar.self]).tintColor = .red
1
Maksim Kniazev

Il semble que Swift (du moins à partir de Beta5) ne soit pas en mesure de le prendre en charge pour des raisons inconnues. Peut-être que la fonctionnalité linguistique requise est toujours en cours, car je ne peux que présumer qu'ils l'ont laissée Comme vous l'avez dit, selon la documentation, il est toujours disponible dans ObjC. Vraiment décevant.

0
hlfcoding