ПоявлениеWhenContainedIn в Swift
Я пытаюсь преобразовать свое приложение в язык Swift.
У меня есть эта строка кода:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
setTitleTextAttributes:textDictionary
forState:UIControlStateNormal];
Как преобразовать его в Swift?
В Apple docs такого метода нет.
Ответы
Ответ 1
Обновление для 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, поскольку методы varargs 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
Просто не забудьте #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
Ответ 2
ios 10 swift 3
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Kapat"
Ответ 3
Для iOS 8 и 7:
Я использую категорию на основе ответа Alex, чтобы указать несколько контейнеров. Это временное решение, пока Apple официально не поддерживает appearanceWhenContainedIn
в Swift.
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, но я не нашел чистого решения.
Ответ 4
Здесь менее уродливое, но все же уродливое, обходное решение, вдохновленное @tdun.
- Создайте класс, чтобы сохранить внешний вид Objective-C. Для целей этого примера позвоните ему
AppearanceBridger
.
- Добавьте этот класс в свой заголовок. Если у вас нет заголовка моста, создать один.
- Создайте метод класса в
AppearanceBridger
с именем +(void)setAppearance
и поместите код внешнего вида Objective-C в этот метод. Например:
+ (void)setAppearance {
[[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}
- В вашем коде Swift, где вы задаете внешний вид, вызовите
AppearanceBridger.setAppearance()
, и вы должны быть добрым!
Надеюсь, это хорошо работает для людей, которые это видят.
Ответ 5
Вот уродливое решение обходного пути, которое я использовал....
Просто создайте Objective-C Cocoa Touch Class (UIViewController), названный так, как вы хотите.
Я назвал мой WorkaroundViewController
...
Теперь в (WorkaroundViewController.m
):
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
Запустите код внешнего вида Objective-C для .appearanceWhenContainedIn()
(здесь мой пример):
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Avenir-Light" size:16.0f]}];
Затем создайте заголовок моста для вашего проекта Swift и затем инициализируйте ваш ViewController Objective-C в вашем Swift-коде, как это (опять же, просто мой пример):
var work : WorkaroundViewController = WorkaroundViewController()
Тогда все готово! Дайте мне знать, если это сработает для вас... Как я уже сказал, это уродливо, но работает!
Ответ 6
Это может быть расширено для любого класса, который соответствует протоколу 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
Ответ 7
Я создал репо для вас, ребята, которые хотят использовать 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)
}
-
Ссылка:
https://github.com/levantAJ/UIViewAppearanceSwift
Ответ 8
Кажется, Swift (по крайней мере, с Beta5) не может поддерживать его по неизвестным мне причинам. Возможно, требуемая языковая функция все еще продолжается, поскольку я могу только предположить, что они оставили ее вне интерфейса по уважительной причине. Как вы сказали, согласно документам, он все еще доступен в ObjC. Действительно неутешительно.
Ответ 9
Вы можете использовать это:
UIBarButtonItem.appearance().setTitleTextAttributes(textDictionary, forState: UIControlState.Normal)
Изменить: внешний видWhenContainedIn был удален в Swift. Этот ответ состоял в том, что Beta 5 изменила внешний вид текста всех кнопок на панели.
Ответ 10
Вы должны просто перевести синтаксис Objective-C
в синтаксис Swift
.
В быстрой версии методы должны быть объявлены следующим образом:
func appearanceWhenContainedIn(containerClass : <UIAppearanceContainer>)
func setTitleTextAttributes(_ attributes: NSDictionary!, forState state: UIControlState)
Итак, вы можете попробовать следующее:
UIBarButtonItem.appearanceWhenContainedIn(UINavigationBar).setTitleTextAttributes(textDictionary, forState: UIControlStateNormal)
Мне все же нужно выяснить, является ли это чистым способом вызова метода класса в Swift
.
Надеюсь, что это поможет,