在Swift中包含的外观
我试图将我的应用程序转换为Swift语言。
我有这样的代码行:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:textDictionary forState:UIControlStateNormal];
如何将其转换为Swift?
在苹果的文档中 ,没有这样的方法。
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:
这些方法不适用于Swift,因为Obj-C可变参数方法与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
只要确保在桥接头文件中input#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"
对于iOS 8和7:
我使用基于Alex的答案来指定多个容器的类别。 这是一个解决方法,直到苹果正式支持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
如果我能find一种使用CVarArgType的方法,这是很好的,但是我没有find干净的解决scheme。
这是一个不那么丑陋,但仍然丑陋,由@tdun启发的解决方法。
- 创build一个类来保存你的Objective-C外观。 为了这个例子的目的,我们称之为
AppearanceBridger
。 - 将这个类添加到您的桥接头。 如果您没有桥接头,请创build一个 。
- 在名为
+(void)setAppearance
AppearanceBridger
创build一个类方法,并将Objective-C外观代码放在此方法中。 例如:
+ (void)setAppearance { [[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]]; }
- 在您设置外观的Swift代码中,调用
AppearanceBridger.setAppearance()
,您应该很好!
希望这对那些看到它的人很好。
这是一个丑陋的解决方法,我用….
只要制作一个Objective-Ccocoa触摸类(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项目创build一个桥接头 ,然后在你的Swift代码中初始化你的Objective-C ViewController,就像这样(再次,就是我的例子):
var work : WorkaroundViewController = WorkaroundViewController()
那你就完成了! 让我知道,如果它适合你…就像我说的,这是丑陋的,但工作!
这可以扩展到任何符合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
我为你们想要使用CocoaPods
人创build了一个回购:
-
将其添加到您的
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) }
-
参考: https : //github.com/levantAJ/UIViewAppearanceSwift
看来Swift(至less从Beta5开始)不能以我未知的原因来支持它。 也许所需的语言function仍在进行中,因为我只能假设他们将其从界面中排除出去是有原因的。 就像你说的那样,根据文档,它仍然可以在ObjC中find。 真令人失望。
你可以使用这个:
UIBarButtonItem.appearance().setTitleTextAttributes(textDictionary, forState: UIControlState.Normal)
编辑:appearanceWhenContainedIn在Swift中被删除。 这个答案是为了改变所有酒吧button的文字的外观。
您应该能够将Objective-C
语法转换为Swift
语法。
在迅速的方法应该这样宣布:
func appearanceWhenContainedIn(containerClass : <UIAppearanceContainer>) func setTitleTextAttributes(_ attributes: NSDictionary!, forState state: UIControlState)
所以你可以试试这个:
UIBarButtonItem.appearanceWhenContainedIn(UINavigationBar).setTitleTextAttributes(textDictionary, forState: UIControlStateNormal)
我仍然需要弄清楚这是否是在Swift
调用类方法的干净方式。
希望这可以帮助,