web-dev-qa-db-ja.com

SwiftのappearanceWhenContainedIn

アプリをSwift言語に変換しようとしています。

次のコード行があります。

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

Swiftに変換する方法は?

Appleのドキュメント では、そのような方法はありません。

124
AlexZd

IOS 9の更新:

IOS 9以降(Xcode 7 b1の時点)をターゲットにしている場合、可変引数を使用しないUIAppearanceプロトコルに新しいメソッドがあります。

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

次のように使用できます:

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

IOS 8以前をまだサポートする必要がある場合は、この質問に対する次の元の回答を使用してください。

IOS 8および7の場合:

Obj-C可変引数メソッドはSwiftと互換性がないため、これらのメソッドはSwiftで使用できません( http://www.openradar.me/17302764 を参照してください) )。

私はSwiftで機能する非バリアックな回避策を書きました(UIBarItemから派生しない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

必ず、ブリッジングヘッダーで#import "UIAppearance+Swift.h"にしてください。

次に、Swiftから呼び出す(たとえば):

# 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

IOS 8および7の場合:

アレックスの答えに基づいたカテゴリを使用して、複数のコンテナを指定します。これは、SwiftでAppleがappearanceWhenContainedInを公式にサポートするまでの回避策です。

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

次に、#import "UIAppearance+Swift.h"をブリッジングヘッダーに追加します。

Swiftから使用するには

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

CVarArgType を使用して方法を見つけることができれば良かったのですが、きれいな解決策は見つかりませんでした。

14
Yoichi Tagaya

これは@tdunに触発された、それほど見苦しくはありませんが、依然として見苦しい回避策です。

  1. Objective-Cの外観を保持するクラスを作成します。この例の目的のために、AppearanceBridgerと呼びましょう。
  2. このクラスをブリッジングヘッダーに追加します。ブリッジングヘッダーがない場合は、 作成 です。
  3. AppearanceBridgerという名前の+(void)setAppearanceというクラスメソッドを作成し、このメソッドにObjective-Cの外観コードを配置します。例えば:

+ (void)setAppearance {
    [[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}
  1. 外観を設定したSwiftコードでAppearanceBridger.setAppearance()を呼び出すと、準備完了です!

これを見る人々にうまく機能することを願っています。

12
Baub

これは、UIViewだけでなく、UIAppearanceプロトコルに準拠する任意のクラスに拡張できます。そこで、より一般的なバージョンを次に示します。

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

ここに私が使ったい回避策があります。

任意の名前を付けたObjective-C Cocoa Touchクラス(UIViewController)を作成するだけです。

私の名前はWorkaroundViewController...

今(WorkaroundViewController.m):

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

.appearanceWhenContainedIn()のObjective-C外観コードを実行します(ここに私の例があります):

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

次に、 ブリッジヘッダーを作成 Swiftプロジェクトに対して、次にSwiftコードでObjective-C ViewControllerを初期化します(これも私の例です) :

var work : WorkaroundViewController = WorkaroundViewController()

これで完了です!それがあなたのために働くかどうか教えてください...私が言ったように、それはいですが、動作します!

4
tcd

CocoaPodsを使用したい皆さんのためにレポを作成しました:

  1. これをPodfileに追加します:

    pod 'UIViewAppearanceSwift'
    
  2. クラスにインポートします。

    import UIViewAppearanceSwift
    
    func layout() {
        UINavigationBar.appearanceWhenContainedWithin(MFMailComposeViewController.self).barStyle = .Black
        UIBarButtonItem.appearanceWhenContainedWithin(UISearchBar.self).setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(15)], forState: UIControlState.Normal)
    }
    
  3. リファレンス: https://github.com/levantAJ/UIViewAppearanceSwift

3
Tai Le

Swift 4:iOS 9 +

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

Swift(少なくともBeta5以降)は、私には不明な理由でサポートできません。おそらく、必要な言語機能はまだ進行中です。これは、正当な理由でインターフェースから除外したとしか思われないからです。あなたが言ったように、ドキュメントによると、それはまだObjCで利用可能です。本当にがっかり。

0
hlfcoding