アプリをSwift言語に変換しようとしています。
次のコード行があります。
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
setTitleTextAttributes:textDictionary
forState:UIControlStateNormal];
Swiftに変換する方法は?
Appleのドキュメント では、そのような方法はありません。
IOS 9以降(Xcode 7 b1の時点)をターゲットにしている場合、可変引数を使用しないUIAppearance
プロトコルに新しいメソッドがあります。
static func appearanceWhenContainedInInstancesOfClasses(containerTypes: [AnyObject.Type]) -> Self
次のように使用できます:
UITextField.appearanceWhenContainedInInstancesOfClasses([MyViewController.self]).keyboardAppearance = .Light
IOS 8以前をまだサポートする必要がある場合は、この質問に対する次の元の回答を使用してください。
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
ios 10 Swift 3
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Kapat"
アレックスの答えに基づいたカテゴリを使用して、複数のコンテナを指定します。これは、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 を使用して方法を見つけることができれば良かったのですが、きれいな解決策は見つかりませんでした。
これは@tdunに触発された、それほど見苦しくはありませんが、依然として見苦しい回避策です。
AppearanceBridger
と呼びましょう。AppearanceBridger
という名前の+(void)setAppearance
というクラスメソッドを作成し、このメソッドにObjective-Cの外観コードを配置します。例えば:
+ (void)setAppearance {
[[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}
AppearanceBridger.setAppearance()
を呼び出すと、準備完了です!これを見る人々にうまく機能することを願っています。
これは、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
ここに私が使ったい回避策があります。
任意の名前を付けた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()
これで完了です!それがあなたのために働くかどうか教えてください...私が言ったように、それはいですが、動作します!
CocoaPods
を使用したい皆さんのためにレポを作成しました:
これをPodfile
に追加します:
pod 'UIViewAppearanceSwift'
クラスにインポートします。
import UIViewAppearanceSwift
func layout() {
UINavigationBar.appearanceWhenContainedWithin(MFMailComposeViewController.self).barStyle = .Black
UIBarButtonItem.appearanceWhenContainedWithin(UISearchBar.self).setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(15)], forState: UIControlState.Normal)
}
Swift 4:iOS 9 +
UIProgressView.appearance(whenContainedInInstancesOf: [LNPopupBar.self]).tintColor = .red
Swift(少なくともBeta5以降)は、私には不明な理由でサポートできません。おそらく、必要な言語機能はまだ進行中です。これは、正当な理由でインターフェースから除外したとしか思われないからです。あなたが言ったように、ドキュメントによると、それはまだObjCで利用可能です。本当にがっかり。