我正在尝试将我的应用转换为Swift语言。
我有这行代码:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
setTitleTextAttributes:textDictionary
forState:UIControlStateNormal];
如何将其转换为Swift?
在Apple's docs中,没有这样的方法。
答案 0 :(得分:229)
如果您的目标是iOS 9+(从Xcode 7 b1开始),UIAppearance
协议中有一种新方法不使用varargs:
static func appearanceWhenContainedInInstancesOfClasses(containerTypes: [AnyObject.Type]) -> Self
可以这样使用:
UITextField.appearanceWhenContainedInInstancesOfClasses([MyViewController.self]).keyboardAppearance = .Light
如果您仍需要支持iOS 8或更早版本,请使用以下原始答案来解决此问题。
这些方法不适用于Swift,因为Obj-C varargs方法与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
答案 1 :(得分:31)
ios 10 swift 3
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Kapat"
答案 2 :(得分:14)
我使用基于Alex答案的类别来指定多个容器。这是一种解决方法,直到Apple正式支持Swift中的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的方法,那就太好了,但我找不到干净的解决方案。
答案 3 :(得分:12)
这是一个不那么丑陋,但仍然很丑陋的解决方案,受到@tdun的启发。
AppearanceBridger
。AppearanceBridger
的{{1}}中创建一个类方法,并将Objective-C外观代码放在此方法中。例如:
+(void)setAppearance
+ (void)setAppearance {
[[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}
,您应该好好去!希望这对那些看到它的人来说很有效。
答案 4 :(得分:4)
这是我用过的一个丑陋的解决方案....
制作一个Objective-C Cocoa Touch Class(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]}];
然后create a bridging header用于你的Swift项目,然后在你的Swift代码中初始化你的Objective-C ViewController,就像这样(再次,只是我的例子):
var work : WorkaroundViewController = WorkaroundViewController()
然后你就完成了!让我知道它是否对你有用......就像我说的那样,它很难看,但是很有效!
答案 5 :(得分:4)
这可以扩展到任何符合UIAppearance协议的类 - 而不仅仅是UIViews。所以这是一个更通用的版本:
<强> UIAppearance + Swift.h 强>
#import <UIKit/UIKit.h>
@interface NSObject (UIAppearance_Swift)
+ (instancetype)appearanceWhenContainedWithin:(Class<UIAppearanceContainer>)containerClass;
@end
<强> UIAppearance + 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
答案 6 :(得分:3)
我为那些想要使用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)
}
答案 7 :(得分:0)
似乎Swift(至少从Beta5开始)由于我不知道的原因而无法支持它。也许所需的语言功能仍在进行中,因为我只能假设他们将其从界面中删除是有充分理由的。就像你说的那样,根据文档,它仍然可以在ObjC中找到。真的很失望。
答案 8 :(得分:-3)
您可以使用:
UIBarButtonItem.appearance().setTitleTextAttributes(textDictionary, forState: UIControlState.Normal)
编辑:在Swift中删除了appearanceWhenContainedIn。这个答案是针对Beta 5更改所有小节按钮文本的外观。
答案 9 :(得分:-7)
您应该只需将Objective-C
语法翻译成Swift
语法。
在swift中,方法应该像这样声明:
func appearanceWhenContainedIn(containerClass : <UIAppearanceContainer>)
func setTitleTextAttributes(_ attributes: NSDictionary!, forState state: UIControlState)
所以你可以试试这个:
UIBarButtonItem.appearanceWhenContainedIn(UINavigationBar).setTitleTextAttributes(textDictionary, forState: UIControlStateNormal)
我仍然需要弄清楚这是否是在Swift
中调用类方法的简洁方法。
希望这有帮助,