görünümWhenContainedIn Swift


125

Uygulamamı Swift diline dönüştürmeye çalışıyorum.

Bu kod satırına sahibim:

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

Swift'e nasıl dönüştürülür?

In Apple'ın docs , böyle bir yöntem yoktur.


1
@LukeTheObscure aşağıdaki cevabıma bakın ... çirkin, ama işe yarıyor.
tcd

Yanıtlar:


230

İOS 9 güncellemesi:

UIAppearanceİOS 9+ hedefliyorsanız (Xcode 7 b1'den itibaren ), protokolde vararg kullanmayan yeni bir yöntem vardır :

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

Hangisi böyle kullanılabilir:

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

Hala iOS 8 veya önceki bir sürümünü desteklemeniz gerekiyorsa, bu soruya aşağıdaki orijinal cevabı kullanın.

İOS 8 ve 7 için:

Bu yöntemler Swift için mevcut değildir çünkü Obj-C varargs yöntemleri Swift ile uyumlu değildir (bkz. Http://www.openradar.me/17302764 ).

Swift'de çalışan, değişken olmayan bir çözüm yazdım (aynı yöntemi tekrarladım UIBarItem, bunun için inmiyor 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

Sadece #import "UIAppearance+Swift.h"köprü başlığınızda emin olun .

Ardından Swift'den aramak için (örneğin):

# Swift 2.x:
UITextField.my_appearanceWhenContainedIn(MyViewController.self).keyboardAppearance = .Light

# Swift 3.x:
UITextField.my_appearanceWhenContained(in: MyViewController.self).keyboardAppearance = .light

15
UIBarButtonItem bir UIView değil ve ayrı olarak genişletilmesi gerekiyor
Sergey Skoblikov

7
En azından iOS8'de, UIAppearance + Swift.h'nin UIKit / UIKit.h'yi içe aktarması gerektiğini unutmayın
Chase

UIBarButtonItem, UIView yerine UIBarButtonItem'i hedefleyen başka bir yöntem oluşturduğunuzda da desteklenebilir. @interface UIBarButtonItem (UIViewAppearance_Swift)
Michael Peterson

1
@rptwsthi: Swift 3 için bir örnek ekledim, çok az farklı
Alex Pretzlav

1
Swift 3.2 için iOS 9 sürümü, UIBarButtonItem.appearance'dir (whenContainedInInstancesOf: [UISearchBar.self]). Title = "Done"
Eli Burke,

31

ios 10 swift 3

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Kapat"

1
İOS10 swift 3 'te yapmanın yolu bu olduğundan, bunun neden olumsuz oy olduğunu bilmiyorum ... Teşekkürler
Vassily

14

İOS 8 ve 7 için:

Birden çok kapsayıcı belirtmek için Alex'in cevabına dayalı bir kategori kullanıyorum. Bu, Apple resmi appearanceWhenContainedInolarak Swift'i destekleyene kadar geçici bir çözümdür.

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

Ardından #import "UIAppearance+Swift.h"köprü başlığınıza ekleyin .

Swift'den kullanmak için :

TextField.appearanceWhenContainedWithin([MyViewController.self, TableViewController.self]).keyboardAppearance = .Light

CVarArgType kullanarak bir yol bulabilirsem iyiydi , ancak temiz bir çözüm bulamadım.


Vararjların bozukluğuna güzel bir çözüm! Gerçekten çok kötü, (şimdi) Apple'ın yalnızca iOS 9 yöntemini kullanmaktan başka genel bir çözüm yok.
Alex Pretzlav

12

İşte daha az çirkin ama yine de çirkin, @tdun'dan ilham alan bir geçici çözüm.

  1. Objective-C görünümünüzü koruyacak bir sınıf oluşturun. Bu örneğin amaçları için onu arayalım AppearanceBridger.
  2. Bu sınıfı köprü başlığınıza ekleyin. Bir köprü başlığınız yoksa, bir tane oluşturun .
  3. AppearanceBridgerAdlandırılmış bir sınıf yöntemi oluşturun +(void)setAppearanceve Objective-C görünüm kodunu bu yönteme yerleştirin. Örneğin:


+ (void)setAppearance {
    [[UIView appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setBackgroundColor:[UIColor whiteColor]];
}

  1. Görünümü ayarladığınız Swift kodunuzda arayın AppearanceBridger.setAppearance()ve gitmeniz iyi olur!

Umarım bu, onu gören insanlar için iyi çalışır.


4

İşte kullandığım çirkin bir geçici çözüm ...

İstediğiniz adı taşıyan bir Objective-C Cocoa Touch Sınıfı (UIViewController) yapın.

Benimkini seçtim WorkaroundViewController...

Şimdi ( WorkaroundViewController.m) içinde:

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

Objective-C görünüm kodunu çalıştırın .appearanceWhenContainedIn()(işte benim örneğim):

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Avenir-Light" size:16.0f]}];

Sonra Swift projeniz için bir köprüleme başlığı oluşturun ve ardından Objective-C ViewController'ınızı Swift kodunuzda şu şekilde başlatın (yine benim örneğim):

var work : WorkaroundViewController = WorkaroundViewController()

O zaman bitirdiniz! Sizin için işe yarayıp yaramadığını bana bildirin ... Dediğim gibi, çirkin ama işe yarıyor!


Bu tmp çözümü, bence daha iyi bir yol bulmalı veya beklemeliyiz :)
AlexZd

@AlexZd, kesinlikle, umarım hızlı bir şekilde dahil ederler ... Ama şimdilik, ihtiyacınız varsa, işte oraya!
tcd

4

Bu, yalnızca UIViews değil, UIAppearance protokolüne uyan herhangi bir sınıfa genişletilebilir. İşte daha genel bir versiyon:

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

3

Kullanmak isteyen sizler için bir depo oluşturdum CocoaPods:

  1. Bunu şuraya ekle Podfile:

    pod 'UIViewAppearanceSwift'
  2. Sınıfınıza aktarın:

    import UIViewAppearanceSwift
    
    func layout() {
        UINavigationBar.appearanceWhenContainedWithin(MFMailComposeViewController.self).barStyle = .Black
        UIBarButtonItem.appearanceWhenContainedWithin(UISearchBar.self).setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(15)], forState: UIControlState.Normal)
    }
  3. Referans: https://github.com/levantAJ/UIViewAppearanceSwift


1

Swift 4: iOS 9+

UIProgressView.appearance(whenContainedInInstancesOf: [LNPopupBar.self]).tintColor = .red

0

Görünüşe göre Swift (en azından Beta5 itibariyle) benim bilmediğim nedenlerle onu destekleyemiyor. Belki de gerekli olan dil özelliği hala devam ediyor, çünkü sadece iyi bir nedenden dolayı arayüzün dışında bıraktıklarını varsayabilirim. Dediğin gibi, belgelere göre hala ObjC'de mevcut. Gerçekten hayal kırıklığı yaratıyor.


Bu benim için Beta 5'te @spinillos yöntemini kullanarak çalıştı.
Jason Crump

Doğru, ama appearanceWhenContainedIn:yine de masanın dışında.
hlfcoding

-3

Bunu kullanabilirsiniz:

UIBarButtonItem.appearance().setTitleTextAttributes(textDictionary, forState: UIControlState.Normal)

Düzenleme: görünümWhenContainedIn, Swift'de kaldırıldı. Bu cevap, Beta 5'in tüm çubuk düğmelerinin metninin görünümünü değiştirmesiydi.


1
Ayrıca, kullanmaya UIControlState.Normalgerek yok, sadece .NormalSwift türünü çıkarım yoluyla bilir.
Ben Lachman

12
bu, tüm UIBarButtonItems öğelerinin görünümünü değiştirecek, belirli olanlar için değil
Kostiantyn Koval

@KonstantinKoval Kesinlikle - görünüm vekillerinin amacı budur. Her görünüm denetleyicisinde ortak kod / yöntem çağrıları içermeye gerek kalmadan tüm uygulamanızı biçimlendirebilirsiniz.
Craig Otis

3
Bu aslında soruya cevap vermiyor, Swift'de appearanceWhenContainedInkaldırıldı.
Tim Windsor Brown

-7

Sadece çevirmek gerekir Objective-Ciçine sözdizimi Swiftsözdizimi.

Hızlı bir şekilde yöntemler şu şekilde beyan edilmelidir:

func appearanceWhenContainedIn(containerClass : <UIAppearanceContainer>)
func setTitleTextAttributes(_ attributes: NSDictionary!, forState state: UIControlState)

Yani şunu deneyebilirsiniz:

UIBarButtonItem.appearanceWhenContainedIn(UINavigationBar).setTitleTextAttributes(textDictionary, forState: UIControlStateNormal)

Yine de, bunun bir sınıf yöntemini çağırmanın temiz yolu olup olmadığını anlamalıyım Swift.

Bu yardımcı olur umarım,


1
Bu yöntem yok, görünümWhenContainedIn swift içinde derlenmez. Hata: 'UIBarButtonItem.Type', 'görünümWhenContainedIn' adlı bir üyeye sahip değil
AlexZd

Merhaba @AlexZd, yorumunuz gerçek XCode 6 Beta'ya dayanıyor ancak UIAppearanceprotokol belgelerine bakarsanız (bunlara UIBarButtonItemuyuyor), `görünümWhenContainedIn (_ :) yöntemi var (henüz Swift'de uygulanmadı): developer.apple .com / library / prerelease / ios / document / UIKit /…
Zedenem

@Zedenem Biliyorum, gerçekten aptalca ve bize inanmak istemiyorsunuz - ama bu yöntem tam anlamıyla Swift'den çağrılamaz, belgeleri kontrol edin: developer.apple.com/library/ios/documentation/UIKit/Reference/… - yöntem
Swift'den

Merhaba @ powerj1984, sana inanmak istemediğimden değil. Cevabımı yazdığım sırada bunun Swift'in beta statüsünden kaynaklandığını umuyordum. Yöntemin kullanımdan kaldırılmamış olması, sadece Swift'den gizlenmiş olması gerçekten garip ve Apple'dan hiçbir açıklama yapmaması onu daha da kötü hale getiriyor ... Ama haklısın, nedenini anlamasam bile, cevabım Hata. Belki
Swift'de

Haha, özür dilerim - gerçekten bana inanmak istemediğimi söylüyorum. Apple'ın çuvallaması çok aptalca bir şey. Bu çok tuhaf!
powerj1984
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.