কীভাবে সুইফটে গণনা মানটির নাম পাবেন?


167

আমার যদি কাঁচা Integerমান সহ একটি গুন থাকে :

enum City: Int {
  case Melbourne = 1, Chelyabinsk, Bursa
}

let city = City.Melbourne

আমি কীভাবে কোনও cityমানকে স্ট্রিংয়ে রূপান্তর করতে পারি Melbourne? ভাষাতে কি এই জাতীয় নামের অন্তর্নিবেশ রয়েছে?

এর মতো কিছু (এই কোডটি কার্যকর করবে না):

println("Your city is \(city.magicFunction)")
> Your city is Melbourne

উত্তর:


139

এক্সকোড 7 বিটা 5 (সুইফ্ট সংস্করণ 2) হিসাবে আপনি এখন টাইপ নাম এবং এনাম কেসগুলি ডিফল্টরূপে ব্যবহার করে মুদ্রণ করতে পারেন print(_:), বা এর আরম্ভকারী বা স্ট্রিং ইন্টারপোলেশন সিনট্যাক্স Stringব্যবহার করে রূপান্তর করতে পারেন । সুতরাং আপনার উদাহরণের জন্য:Stringinit(_:)

enum City: Int {
    case Melbourne = 1, Chelyabinsk, Bursa
}
let city = City.Melbourne

print(city)
// prints "Melbourne"

let cityName = "\(city)"   // or `let cityName = String(city)`
// cityName contains "Melbourne"

সুতরাং কোনও স্ট্রিং আক্ষরিক ফিরে আসতে প্রতিটি ক্ষেত্রে স্যুইচ করে এমন কোনও সুবিধার ফাংশন সংজ্ঞায়িত এবং বজায় রাখার দরকার নেই। উপরন্তু, এটি কোনও এনামের জন্য স্বয়ংক্রিয়ভাবে কাজ করে, এমনকি কোনও কাঁচা-মান প্রকার নির্দিষ্ট না করে।

debugPrint(_:)& String(reflecting:)সম্পূর্ণরূপে যোগ্য নামের জন্য ব্যবহার করা যেতে পারে:

debugPrint(city)
// prints "App.City.Melbourne" (or similar, depending on the full scope)

let cityDebugName = String(reflecting: city)
// cityDebugName contains "App.City.Melbourne"

নোট করুন যে আপনি এই পরিস্থিতিতে প্রতিটি মুদ্রিত কি কাস্টমাইজ করতে পারেন:

extension City: CustomStringConvertible {
    var description: String {
        return "City \(rawValue)"
    }
}

print(city)
// prints "City 1"

extension City: CustomDebugStringConvertible {
    var debugDescription: String {
        return "City (rawValue: \(rawValue))"
    }
}

debugPrint(city)
// prints "City (rawValue: 1)"

(আমি এই "ডিফল্ট" মানটিতে কল করার কোনও উপায় খুঁজে পাইনি, উদাহরণস্বরূপ, "শহরটি মেলবোর্ন" মুদ্রণ করার জন্য কোনও সুইচ বিবৃতিতে ফিরে না গিয়েই ব্যবহার করা / \(self)কার্যকর করার ক্ষেত্রে description/ debugDescriptionঅসীম পুনরাবৃত্তি ঘটায়।)


উপরে মন্তব্য Stringএর init(_:)& init(reflecting:)initializers, বর্ণনা ঠিক কি ছাপা হয় কি প্রতিফলিত টাইপ কে কনর্ফাম করে উপর ভিত্তি করে:

extension String {
    /// Initialize `self` with the textual representation of `instance`.
    ///
    /// * If `T` conforms to `Streamable`, the result is obtained by
    ///   calling `instance.writeTo(s)` on an empty string s.
    /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the
    ///   result is `instance`'s `description`
    /// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`,
    ///   the result is `instance`'s `debugDescription`
    /// * Otherwise, an unspecified result is supplied automatically by
    ///   the Swift standard library.
    ///
    /// - SeeAlso: `String.init<T>(reflecting: T)`
    public init<T>(_ instance: T)

    /// Initialize `self` with a detailed textual representation of
    /// `subject`, suitable for debugging.
    ///
    /// * If `T` conforms to `CustomDebugStringConvertible`, the result
    ///   is `subject`'s `debugDescription`.
    ///
    /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the result
    ///   is `subject`'s `description`.
    ///
    /// * Otherwise, if `T` conforms to `Streamable`, the result is
    ///   obtained by calling `subject.writeTo(s)` on an empty string s.
    ///
    /// * Otherwise, an unspecified result is supplied automatically by
    ///   the Swift standard library.
    ///
    /// - SeeAlso: `String.init<T>(T)`
    public init<T>(reflecting subject: T)
}


এই পরিবর্তন সম্পর্কে তথ্যের জন্য প্রকাশের নোটগুলি দেখুন ।


8
এছাড়াও আপনি যদি স্ট্রিংয়ের মানটি ব্যবহার print(enum)না করেও ব্যবহার করতে পারেন তবেString(enum)
কামেট্রিক্সম

44
গুরুত্বপূর্ণ ক্যাচ, এটি কেবল সুইফ্ট এনামগুলিতে কাজ করে। আপনি যদি ওএস এক্স-এ বাধ্যতামূলক সমর্থনকে অনুমতি দেওয়ার জন্য @objc এ ট্যাগ করেন তবে এটি কার্যকর হবে না।
ক্লজ জারজেনসেন

11
দুর্দান্ত সুইফট-নির্দিষ্ট উত্তর; তবে, আপনার যদি CLAuthorizationStatusআপনার locationManager didChangeAuthorizationStatusডেলিগেট কলব্যাকের অভ্যন্তরে (অবজেক্টিভ সি) এনামের মান প্রিন্ট করার জন্য কোনও নন-সুইফ্ট এনামে এটি করার দরকার হয় তবে আপনাকে একটি প্রোটোকল এক্সটেনশান সংজ্ঞায়িত করতে হবে। উদাহরণস্বরূপ: extension CLAuthorizationStatus: CustomStringConvertable { public var description: String { switch self { case .AuthorizedAlways: return "AuthorizedAlways" <etc> } } }- একবার আপনি এটি করার পরে, এটি আপনার প্রত্যাশার মতো কাজ করা উচিত: মুদ্রণ করুন ("এথ স্ট্যাটাস: (\ স্ট্যাটাস))"।
জেফ্রো

3
"এক্সকোড 7 বিটা 5 হিসাবে" অর্থহীন। এটি এক্সকোড নয় যা এর কোনও সংজ্ঞা দেয়, এটি সুইফট সংকলক এবং সুইফট রানটাইম লাইব্রেরি। আমি এক্সকোড 9.3 ব্যবহার করতে পারি তবে আমার কোডটি এখনও সুইফ্ট 3 হতে পারে এবং তারপরে আমি সুইফট 4 বৈশিষ্ট্যগুলি ব্যবহার করতে সক্ষম হবো না। এক্সকোড 9.3 ব্যবহার করে, এই কোডটি Xcode 9.3 Xcode 7 এর চেয়ে অনেক নতুন হওয়া সত্ত্বেও কাজ করে না
মেকি

8
আমি ইনিশিয়ালাইজার পেয়েছি 'আরআইআই (_ :)' দরকার যে সিটি এক্সকোড 10.2, সুইফট 5-তে 'লসসলেস স্ট্রিংকনভার্টেবল' অনুসারে চলে? আমরা এখন এটি কীভাবে করব?
রকজেকো

73

এই মুহুর্তে এনাম কেসগুলিতে কোনও আত্মপরিচয় নেই। আপনাকে সেগুলি প্রতিটি নিজেই ঘোষণা করতে হবে:

enum City: String, CustomStringConvertible {
    case Melbourne = "Melbourne"
    case Chelyabinsk = "Chelyabinsk"
    case Bursa = "Bursa"

    var description: String {
        get {
            return self.rawValue
        }
    }
}

আপনার যদি কোনও অন্তর্নির্মিত হওয়ার জন্য কাঁচা প্রকারের প্রয়োজন হয় তবে আপনাকে নিজেরাই স্যুইচ করতে হবে:

enum City: Int, CustomStringConvertible {
  case Melbourne = 1, Chelyabinsk, Bursa

  var description: String {
    get {
      switch self {
        case .Melbourne:
          return "Melbourne"
        case .Chelyabinsk:
          return "Chelyabinsk"
        case .Bursa:
          return "Bursa"
      }
    }
  }
}

2
খুব গুরুত্বপূর্ণ প্রশ্ন, তবে কেন কেবল স্ব। মূল্য ফেরানোর পরিবর্তে "রিটার্ন সেলফ্রেভালিউ" পাবেন? আমি পরে চেষ্টা করেছি এবং এটি ঠিক কাজ করে।
চক ক্রুটসিংগার

আপনি get { ... }যদি সেটারকে সংজ্ঞায়িত না করেন তবে আপনি ব্রিভিটির অংশটি বাদ দিতে পারেন।
iosdude

1
দুর্দান্ত উত্তরের জন্য ধন্যবাদ। এক্সকোড 7.3 এ, আমি পেয়েছি: "মুদ্রণযোগ্যটির নাম কাস্টমস্ট্রিংকনভার্টেবল করা হয়েছে"। সমাধানটি সহজ - উপরের প্রথম কোড উদাহরণে প্রথম লাইনটি এতে পরিবর্তন করুন enum City : String, CustomStringConvertible {। সিএসসি প্রোটোকলের অংশ হিসাবে, আপনাকে তখন সম্পত্তিটি সর্বজনীন হতে হবে , উদাহরণস্বরূপ:public var description : String {
জেফ্রো

44

সুইফট -3 এ (এক্সকোড 8.1 দিয়ে পরীক্ষা করা) আপনি আপনার এনামটিতে নিম্নলিখিত পদ্ধতিগুলি যুক্ত করতে পারেন:

/**
 * The name of the enumeration (as written in case).
 */
var name: String {
    get { return String(describing: self) }
}

/**
 * The full name of the enumeration
 * (the name of the enum plus dot plus the name as written in case).
 */
var description: String {
    get { return String(reflecting: self) }
}

তারপরে আপনি এটিকে আপনার এনাম উদাহরণগুলিতে একটি সাধারণ পদ্ধতি কল হিসাবে ব্যবহার করতে পারেন। এটি পূর্ববর্তী সুইফ্ট সংস্করণগুলিতেও কাজ করতে পারে তবে আমি এটি পরীক্ষা করি নি।

আপনার উদাহরণে:

enum City: Int {
    case Melbourne = 1, Chelyabinsk, Bursa
    var name: String {
        get { return String(describing: self) }
    }
    var description: String {
        get { return String(reflecting: self) }
    }
}
let city = City.Melbourne

print(city.name)
// prints "Melbourne"

print(city.description)
// prints "City.Melbourne"

আপনি যদি আপনার সমস্ত এনামগুলিতে এই কার্যকারিতাটি সরবরাহ করতে চান তবে আপনি এটিকে একটি এক্সটেনশন করতে পারেন:

/**
 * Extend all enums with a simple method to derive their names.
 */
extension RawRepresentable where RawValue: Any {
  /**
   * The name of the enumeration (as written in case).
   */
  var name: String {
    get { return String(describing: self) }
  }

  /**
   * The full name of the enumeration
   * (the name of the enum plus dot plus the name as written in case).
   */
  var description: String {
    get { return String(reflecting: self) }
  }
}

এটি কেবল সুইফ্ট এনামগুলিতে কাজ করে।


18

অবজেক্টিভ-সি enumএর জন্য বর্তমানে একমাত্র উপায় মনে হচ্ছে উদাহরণস্বরূপ, CustomStringConvertibleএমন কিছু দিয়ে শেষ করে এনাম প্রসারিত করা:

extension UIDeviceBatteryState: CustomStringConvertible {
    public var description: String {
        switch self {
        case .Unknown:
            return "Unknown"
        case .Unplugged:
            return "Unplugged"
        case .Charging:
            return "Charging"
        case .Full:
            return "Full"
        }
    }
}

এবং তারপরে এই enumহিসাবে ingালাই String:

String(UIDevice.currentDevice().batteryState)

12

String(describing:)সূচনাকারী এমনকি অ স্ট্রিং rawValues সঙ্গে enums কেনার ক্ষেত্রে দেখা লেবেলের নাম আসতে ব্যবহার করা যেতে পারে:

enum Numbers: Int {
    case one = 1
    case two = 2
}

let one = String(describing: Numbers.one) // "one"
let two = String(describing: Numbers.two) // "two"

মনে রাখবেন যে এনাম যদি সংশোধক ব্যবহার করে তবে এটি কাজ করে না@objc :

https://forums.swift.org/t/why-is-an-enum-returning-enumname-rather-than-caselabel-for-string-describing/27327

অবজেক্টিভ-সি প্রকারের জন্য উত্পন্ন উত্সযুক্ত ইন্টারফেস কখনও কখনও @objcসংশোধককে অন্তর্ভুক্ত করে না । তবুও এনামগুলি উদ্দেশ্য-সি-তে সংজ্ঞায়িত করা হয়েছে এবং এটি উপরের মতো কাজ করে না।


7

সুইফট ২.২-তে এনামগুলিতে স্ট্রিং (…) (কাস্টমস্ট্রিংকনভার্টেবল) সমর্থন শীর্ষে, তাদের জন্য কিছুটা ভাঙা প্রতিবিম্ব সমর্থনও রয়েছে। সম্পর্কিত মানগুলির সাথে এনাম ক্ষেত্রে ক্ষেত্রে প্রতিবিম্ব ব্যবহার করে এনাম কেসের লেবেল পাওয়া সম্ভব:

enum City {
    case Melbourne(String)
    case Chelyabinsk
    case Bursa

    var label:String? {
        let mirror = Mirror(reflecting: self)
        return mirror.children.first?.label
    }
}

print(City.Melbourne("Foobar").label) // prints out "Melbourne"

ভাঙা হয়ে, আমি তবে বোঝাতে চেয়েছিলাম যে "সরল" এনামগুলির জন্য, উপরের প্রতিচ্ছবি ভিত্তিক labelগণিত সম্পত্তি কেবল ফিরে আসে nil(বু-হু)।

print(City.Chelyabinsk.label) // prints out nil

স্পষ্টতই সুইফট 3 এর পরে প্রতিবিম্বের পরিস্থিতি আরও ভাল হওয়া উচিত। String(…)অন্যান্য উত্তরগুলির মধ্যে একটিতে যেমন পরামর্শ দেওয়া হয়েছে তেমন সমাধান এখনই :

print(String(City.Chelyabinsk)) // prints out Cheylabinsk

2
এটি var label:String { let mirror = Mirror(reflecting: self); if let label = mirror.children.first?.label { return label } else { return String(describing:self) } }
ডেভিড জেমস

5

এটি এত হতাশাজনক।

ক্ষেত্রে যখন আপনার এই নামগুলির দরকার হয় (যে সংকলকটি সঠিক বানানটি পুরোপুরি জানে, তবে অ্যাক্সেস দিতে অস্বীকার করেছে - ধন্যবাদ সুইফট দলকে !! -) তবে স্ট্রিংকে আপনার এনামের বেস তৈরি করতে বা করতে পারবেন না, একটি ভার্জোজ, জটিল বিকল্প নিম্নরূপ:

enum ViewType : Int, Printable {

    case    Title
    case    Buttons
    case    View

    static let all = [Title, Buttons, View]
    static let strings = ["Title", "Buttons", "View"]

    func string() -> String {
        return ViewType.strings[self.rawValue]
    }

    var description:String {
        get {
            return string()
        }
    }
}

আপনি নীচের হিসাবে উপরের ব্যবহার করতে পারেন:

let elementType = ViewType.Title
let column = Column.Collections
let row = 0

println("fetching element \(elementType), column: \(column.string()), row: \(row)")

এবং আপনি প্রত্যাশিত ফলাফল পাবেন (কলামের জন্য কোড অনুরূপ, তবে দেখানো হয়নি)

fetching element Title, column: Collections, row: 0

উপরের দিকে, আমি descriptionসম্পত্তিটি stringপদ্ধতিটিতে আবার উল্লেখ করেছি , তবে এটি স্বাদের বিষয়। আরও মনে রাখবেন যে তথাকথিত staticভেরিয়েবলগুলি তাদের ঘেরের প্রকারের নাম অনুসারে স্কোপ যোগ্য হতে হবে, কারণ সংকলকটি খুব অ্যামনেসিক এবং প্রসঙ্গটি নিজেই স্মরণ করতে পারে না ...

সুইফট দলকে সত্যই কমান্ড করতে হবে। তারা এনাম তৈরি করেছে যে আপনি পারবেন না enumerateএবং যা আপনি ব্যবহার করতে পারবেন enumerateতা "সিকোয়েন্সস" তবে তা নয় enum!


এটি বিবরণে স্ট্রিং (প্রতিফলিত: স্ব) কেবল না করে বরং দীর্ঘ সময় বয়ে যায় বলে মনে হয়।
বুন

4

আমি এই প্রশ্নটিতে ঝাঁপিয়ে পড়েছি এবং উল্লিখিত ম্যাজিক ফাংশনটি তৈরি করার একটি সহজ উপায় ভাগ করতে চেয়েছি

enum City: Int {
  case Melbourne = 1, Chelyabinsk, Bursa

    func magicFunction() -> String {
        return "\(self)"
    }
}

let city = City.Melbourne
city.magicFunction() //prints Melbourne

3

সুইফ্টের এখন যা রয়েছে পুরোপুরি নির্ধারিত কাঁচা মান হিসাবে পরিচিত । মূলত যদি আপনি প্রতিটি কেসকে কাঁচা মান না দেন এবং এনাম স্ট্রিং টাইপের হয় তবে এটি কেটে যায় যে কেসের কাঁচা মান নিজেই স্ট্রিং ফর্ম্যাটে রয়েছে। একবার চেষ্টা করে দেখুন

enum City: String {
  case Melbourne, Chelyabinsk, Bursa
}

let city = City.Melbourne.rawValue

// city is "Melbourne"

3

সুইফ্টের জন্য:

extension UIDeviceBatteryState: CustomStringConvertible {

    public var description: String {
        switch self {
        case .unknown:
            return "unknown"
        case .unplugged:
            return "unplugged"
        case .charging:
            return "charging"
        case .full:
            return "full"
        }
    }

}

যদি আপনার পরিবর্তনশীল "ব্যাটারিস্টেট" থাকে তবে কল করুন:

self.batteryState.description

1

সাধারণ কিন্তু কাজ করে ...

enum ViewType : Int {
    case    Title
    case    Buttons
    case    View
}

func printEnumValue(enum: ViewType) {

    switch enum {
    case .Title: println("ViewType.Title")
    case .Buttons: println("ViewType.Buttons")
    case .View: println("ViewType.View")
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.