appearanceWainContainedIn在Swift中

时间:2014-06-10 09:01:50

标签: ios swift uiappearance

我正在尝试将我的应用转换为Swift语言。

我有这行代码:

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

如何将其转换为Swift?

Apple's docs中,没有这样的方法。

10 个答案:

答案 0 :(得分:229)

iOS 9更新:

如果您的目标是iOS 9+(从Xcode 7 b1开始),UIAppearance协议中有一种新方法不使用varargs:

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

可以这样使用:

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

如果您仍需要支持iOS 8或更早版本,请使用以下原始答案来解决此问题。

适用于iOS 8& 7:

这些方法不适用于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)

适用于iOS 8&amp; 7:

我使用基于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的启发。

  1. 创建一个类来保存Objective-C外观。出于此示例的目的,我们将其称为AppearanceBridger
  2. 将此类添加到桥接标头中。如果您没有桥接标题create one
  3. 在名为AppearanceBridger的{​​{1}}中创建一个类方法,并将Objective-C外观代码放在此方法中。例如:
  4. +(void)setAppearance

    1. 在您设置外观的Swift代码中,请致电 + (void)setAppearance { [[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]]; } ,您应该好好去!
    2. 希望这对那些看到它的人来说很有效。

答案 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的人创建了一个回购:

  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

答案 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中调用类方法的简洁方法。

希望这有帮助,