उपस्थिति। स्विफ्ट में


125

मैं अपने ऐप को स्विफ्ट भाषा में बदलने की कोशिश कर रहा हूं।

मेरे पास कोड की यह पंक्ति है:

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

इसे स्विफ्ट में कैसे बदलें?

में एप्पल के डॉक्स , ऐसी कोई विधि है।


1
@LukeTheObscure नीचे मेरे जवाब की जाँच करें ... बदसूरत, लेकिन काम करता है।
टीसीपी

जवाबों:


230

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 के लिए:

ये विधियां स्विफ्ट के लिए उपलब्ध नहीं हैं क्योंकि ओबज-सी वैरग तरीके स्विफ्ट के साथ संगत नहीं हैं (देखें http://www.openradar.me/17302764 )।

मैंने एक नॉन-वैरडिक वर्कअराउंड लिखा, जो स्विफ्ट में काम करता है (मैंने उसी तरीके को दोहराया 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 2.x:
UITextField.my_appearanceWhenContainedIn(MyViewController.self).keyboardAppearance = .Light

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

15
UIBarButtonItem एक UIView नहीं है और इसे अलग से विस्तारित करने की आवश्यकता है
सर्गेई स्कोब्लिकोव

7
ध्यान दें कि कम से कम iOS8 में, UIAppearance + Swift.h को UIKit / UIKit.h आयात करना चाहिए
Chase

UIBarButtonItem का समर्थन तब भी किया जा सकता है यदि आप UIView के बजाय UIBarButtonItem को लक्षित करने का कोई अन्य तरीका बनाते हैं। @interface UIBarButtonItem (UIViewAppearance_Swift)
माइकल पीटरसन

1
@rptwsthi: मैंने स्विफ्ट 3 के लिए एक उदाहरण जोड़ा है, यह बहुत अलग है
एलेक्स प्रेट्ज़लाव

1
Swift 3.2 के लिए iOS 9 संस्करण UIBarButtonItem.appearance (जबContainInInstancesOf: [UISearchBar. स्वयं]) है। शीर्षक = "संपन्न"
एली

31

ios 10 swift 3

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

1
पता नहीं क्यों यह downvote है क्योंकि यह iOS10 स्विफ्ट 3 में ऐसा करने का तरीका है ... धन्यवाद
Vassily

14

IOS 8 और 7 के लिए:

मैं कई कंटेनरों को निर्दिष्ट करने के लिए एलेक्स के जवाब के आधार पर एक श्रेणी का उपयोग करता हूं। यह एक वर्कअराउंड है जब तक कि Apple आधिकारिक तौर 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"अपने ब्रिजिंग हेडर में जोड़ें ।

स्विफ्ट से उपयोग करने के लिए :

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

यह अच्छा था अगर मुझे CVarArgType का उपयोग करने का एक तरीका मिल जाता , लेकिन मुझे कोई साफ समाधान नहीं मिला।


वर्गास के टूटे-नेस पर अच्छा काम! यह वास्तव में बहुत बुरा है एप्पल के iOS 9-केवल विधि का उपयोग करने के अलावा (अब) कोई अन्य सामान्य समाधान नहीं है।
एलेक्स प्रेट्ज़लाव

12

यहाँ कम बदसूरत है, लेकिन अभी भी बदसूरत है, @tdun से प्रेरित है।

  1. अपने उद्देश्य-सी उपस्थिति को रखने के लिए एक कक्षा बनाएँ। इस उदाहरण के प्रयोजनों के लिए, आइए इसे कहते हैं AppearanceBridger
  2. इस वर्ग को अपने ब्रिजिंग हेडर में जोड़ें। यदि आपके पास ब्रिजिंग हेडर नहीं है, तो एक बनाएं
  3. AppearanceBridgerनामित में एक वर्ग विधि बनाएँ +(void)setAppearanceऔर इस पद्धति में उद्देश्य-सी उपस्थिति कोड डालें। उदाहरण के लिए:


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

  1. अपने स्विफ्ट कोड में जहां आप उपस्थिति सेट करते हैं, कॉल करें AppearanceBridger.setAppearance()और आपको जाने के लिए अच्छा होना चाहिए!

आशा है कि यह उन लोगों के लिए अच्छा काम करेगा जो इसे देखते हैं।


4

यहाँ एक बदसूरत वर्कअराउंड समाधान है जिसका मैंने इस्तेमाल किया था ...।

बस एक ऑब्जेक्टिव-सी कोकोआ टच क्लास (UIViewController) बनाएं, जिसका नाम आप चाहें।

मैंने अपना नाम WorkaroundViewController...

अब ( WorkaroundViewController.m):

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

.appearanceWhenContainedIn()(यहाँ मेरे उदाहरण के लिए) उद्देश्य-सी उपस्थिति कोड चलाएँ :

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

फिर अपने स्विफ्ट प्रोजेक्ट के लिए एक ब्रिजिंग हेडर बनाएं और फिर अपने स्विफ्ट कोड में अपने ऑब्जेक्टिव-सी व्यूकंट्रोलर को इनिशियलाइज़ करें, जैसे कि (फिर, सिर्फ मेरा उदाहरण):

var work : WorkaroundViewController = WorkaroundViewController()

फिर आप कर रहे हैं! मुझे पता है अगर यह तुम्हारे लिए काम करता है ... जैसा मैंने कहा, यह बदसूरत है, लेकिन काम करता है!


यह tmp समाधान है, मुझे लगता है कि हमें ढूंढना चाहिए या कुछ बेहतर तरीके से इंतजार करना चाहिए :)
AlexZd

@AlexZd, बिल्कुल, मुझे आशा है कि वे इसे तेजी से शामिल करते हैं ... लेकिन अभी के लिए, यदि आपको इसकी आवश्यकता है, तो वहां जाएं!
tcd

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

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



0

ऐसा लगता है कि स्विफ्ट (कम से कम बीटा 5 के रूप में) मेरे लिए अज्ञात कारणों से इसका समर्थन करने में सक्षम नहीं है। शायद आवश्यक भाषा सुविधा अभी भी प्रगति पर है, क्योंकि मैं केवल यह मान सकता हूं कि उन्होंने इसे एक अच्छे कारण के लिए इंटरफ़ेस से बाहर छोड़ दिया। जैसा कि आपने कहा, डॉक्स के अनुसार यह अभी भी ओबजेक में उपलब्ध है। वास्तव में निराशाजनक है।


यह मेरे लिए बीटा 5 में @spinillos विधि का उपयोग करके काम किया।
जेसन क्रम्प

ठीक है, लेकिन appearanceWhenContainedIn:अभी भी मेज से दूर है।
hlfcoding

-3

आप इसका उपयोग कर सकते हैं:

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

संपादित करें: उपस्थिति जब स्विफ्ट में हटा दिया गया था। यह उत्तर बीटा 5 के लिए सभी बार बटन के पाठ की उपस्थिति को बदलने के लिए था।


1
इसके अलावा, UIControlState.Normalआप का उपयोग करने की कोई जरूरत नहीं है बस .Normalस्विफ्ट का उपयोग कर सकते हैं पता चल जाएगा inference द्वारा।
बेन लछमन

12
यह सभी UIBarButtonItems के लिए उपस्थिति बदल देगा, विशिष्ट एक के लिए नहीं
Kostiantyn कोवल

@KonstantinKoval वास्तव में - यह उपस्थिति का उद्देश्य है। आप प्रत्येक दृश्य नियंत्रक में बॉयलरप्लेट कोड / मेथड कॉल की आवश्यकता के बिना अपने पूरे आवेदन को स्टाइल कर सकते हैं।
क्रेग ओटिस

3
यह वास्तव में सवाल का जवाब नहीं देता है, स्विफ्ट appearanceWhenContainedInमें हटा दिया गया है।
टिम विंडसर ब्राउन

-7

आपको Objective-Cसिंटैक्स को Swiftसिंटैक्स में अनुवाद करने में सक्षम होना चाहिए ।

स्विफ्ट में तरीकों को इस तरह घोषित किया जाना चाहिए:

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

तो आप यह कोशिश कर सकते हैं:

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

मुझे अभी भी यह पता लगाना है कि क्या यह क्लास पद्धति को कॉल करने का सबसे अच्छा तरीका है Swift

उम्मीद है की यह मदद करेगा,


1
यह कोई भी तरीका नहीं है। त्रुटि: 'UIBarButtonItem.Type' के पास 'उपस्थिति' नाम का सदस्य नहीं है '
एलेक्सजेड

हाय @AlexZd, आपकी टिप्पणी वास्तविक XCode 6 बीटा पर आधारित है, लेकिन यदि आप UIAppearanceप्रोटोकॉल प्रलेखन (जिस पर UIBarButtonItemपुष्टि करते हैं) को देखते हैं, तो `उपस्थितिWhenContainIn (_ :) विधि मौजूद है (यह अभी स्विफ्ट में लागू नहीं हुआ है: developer.apple .com /
Library

@Zedenem मुझे पता है, यह वास्तव में गूंगा है और आप ने हम पर भरोसा नहीं करना चाहते हैं - लेकिन इस विधि सचमुच स्विफ्ट से नहीं कहा जा सकता, प्रलेखन जाँच: developer.apple.com/library/ios/documentation/UIKit/Reference/... - विधि स्विफ्ट से छिपी हुई है
powerj1984

हाय @ powerj1984, ऐसा नहीं है कि मैं आपको विश्वास नहीं करना चाहता। मैं उस समय उम्मीद कर रहा था जब मैंने अपना उत्तर लिखा कि यह सिर्फ स्विफ्ट की बीटा स्थिति के कारण था। तथ्य यह है कि इस विधि को पदावनत नहीं किया गया है, लेकिन बस स्विफ्ट से छिपा हुआ है वास्तव में अजीब है, और Apple से कोई स्पष्टीकरण नहीं होने से यह सबसे खराब हो जाता है ... लेकिन आप सही हैं, भले ही मुझे समझ में न आए, मेरा जवाब गलत है। हो सकता है कि स्विफ्ट में एक फीचर है जिसके बारे में मैं यह नहीं सोच रहा हूं कि हमें ऐसा करने की इजाजत होगी ...
ज़ेडेनम

हाहा, क्षमा करें - मेरा वास्तव में मतलब है कि मैं मुझ पर विश्वास नहीं करना चाहता। यह एप्पल के लिए ऐसी ही एक मूर्खतापूर्ण बात है। यह अजीब है बिल्ली के रूप में!
पॉवरज 1984
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.