swift - রথম - ১ম শ্রেণীর প্রশ্ন নমুনা




আমি কীভাবে সুইফট 4 এ এনাম ডিকোডেবল করব? (5)

enum PostType: Decodable {

    init(from decoder: Decoder) throws {

        // What do i put here?
    }

    case Image
    enum CodingKeys: String, CodingKey {
        case image
    }
}

এটি সম্পূর্ণ করার জন্য আমি কী রাখি? এছাড়াও, আমি বলতে পারি যে আমি কেসটিকে এখানে পরিবর্তন করেছি:

case image(value: Int)

আমি কীভাবে এটি ডিকোডেবলের সাথে সামঞ্জস্য করব?

সম্পাদনা এখানে আমার সম্পূর্ণ কোড (যা কাজ করে না)

let jsonData = """
{
    "count": 4
}
""".data(using: .utf8)!

        do {
            let decoder = JSONDecoder()
            let response = try decoder.decode(PostType.self, from: jsonData)

            print(response)
        } catch {
            print(error)
        }
    }
}

enum PostType: Int, Codable {
    case count = 4
}

চূড়ান্ত সম্পাদনা এছাড়াও, এটি এর মতো একটি এনামকে কীভাবে পরিচালনা করবে?

enum PostType: Decodable {
    case count(number: Int)
}

সম্পর্কিত প্রকারের সাহায্যে Codable সাথে সামঞ্জস্য করা Codable

এই উত্তরটি @ হাওয়ার্ড লোভ্যাট-এর অনুরূপ তবে একটি PostTypeCodableForm তৈরি করা এড়িয়ে যায় এবং এর পরিবর্তে Encoder এবং Decoder সম্পত্তি হিসাবে অ্যাপল দ্বারা সরবরাহিত KeyedEncodingContainer টাইপ ব্যবহার করে, যা বয়লারপ্লেট হ্রাস করে।

enum PostType: Codable {
    case count(number: Int)
    case title(String)
}

extension PostType {

    private enum CodingKeys: String, CodingKey {
        case count
        case title
    }

    enum PostTypeCodingError: Error {
        case decoding(String)
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        if let value = try? values.decode(Int.self, forKey: .count) {
            self = .count(number: value)
            return
        }
        if let value = try? values.decode(String.self, forKey: .title) {
            self = .title(value)
            return
        }
        throw PostTypeCodingError.decoding("Whoops! \(dump(values))")
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        switch self {
        case .count(let number):
            try container.encode(number, forKey: .count)
        case .title(let value):
            try container.encode(value, forKey: .title)
        }
    }
}

এই কোডটি এক্সকোড 9 বি 3-তে আমার জন্য কাজ করে।

import Foundation // Needed for JSONEncoder/JSONDecoder

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let decoder = JSONDecoder()

let count = PostType.count(number: 42)
let countData = try encoder.encode(count)
let countJSON = String.init(data: countData, encoding: .utf8)!
print(countJSON)
//    {
//      "count" : 42
//    }

let decodedCount = try decoder.decode(PostType.self, from: countData)

let title = PostType.title("Hello, World!")
let titleData = try encoder.encode(title)
let titleJSON = String.init(data: titleData, encoding: .utf8)!
print(titleJSON)
//    {
//        "title": "Hello, World!"
//    }
let decodedTitle = try decoder.decode(PostType.self, from: titleData)

@ টোকার উত্তরটি প্রসারিত করতে, আপনি খুব এনামে কাঁচা উপস্থাপনযোগ্য মান যুক্ত করতে পারেন এবং একটি switch ছাড়াই এনাম তৈরির জন্য ডিফল্ট alচ্ছিক নির্মাণকারী ব্যবহার করতে switch :

enum MediaType: String, Decodable {
  case audio = "AUDIO"
  case multipleChoice = "MULTIPLE_CHOICES"
  case other

  init(from decoder: Decoder) throws {
    let label = try decoder.singleValueContainer().decode(String.self)
    self = MediaType(rawValue: label) ?? .other
  }
}

এটি কোনও কাস্টম প্রোটোকল ব্যবহার করে বাড়ানো যেতে পারে যা নির্মাণকারীকে রিফ্যাক্টর করতে দেয়:

protocol EnumDecodable: RawRepresentable, Decodable {
  static var defaultDecoderValue: Self { get }
}

extension EnumDecodable where RawValue: Decodable {
  init(from decoder: Decoder) throws {
    let value = try decoder.singleValueContainer().decode(RawValue.self)
    self = Self(rawValue: value) ?? Self.defaultDecoderValue
  }
}

enum MediaType: String, EnumDecodable {
  static let defaultDecoderValue: MediaType = .other

  case audio = "AUDIO"
  case multipleChoices = "MULTIPLE_CHOICES"
  case other
}

কোনও মানকে ডিফল্ট না করে কোনও অবৈধ এনাম মান নির্দিষ্ট করা থাকলে এটি ত্রুটি ছোঁড়ার জন্য সহজেই বাড়ানো যেতে পারে। এই পরিবর্তনের সংক্ষিপ্ততা এখানে উপলভ্য: https://gist.github.com/stephanecopin/4283175fabf6f0cdaf87fef2a00c8128
কোডটি সুইফট ৪.১ / এক্সকোড ৯.৩ ব্যবহার করে সংকলিত এবং পরীক্ষিত হয়েছিল।


আপনি যা চান তা করতে পারেন তবে এটি কিছুটা জড়িত :(

import Foundation

enum PostType: Codable {
    case count(number: Int)
    case comment(text: String)

    init(from decoder: Decoder) throws {
        self = try PostTypeCodableForm(from: decoder).enumForm()
    }

    func encode(to encoder: Encoder) throws {
        try PostTypeCodableForm(self).encode(to: encoder)
    }
}

struct PostTypeCodableForm: Codable {
    // All fields must be optional!
    var countNumber: Int?
    var commentText: String?

    init(_ enumForm: PostType) {
        switch enumForm {
        case .count(let number):
            countNumber = number
        case .comment(let text):
            commentText = text
        }
    }

    func enumForm() throws -> PostType {
        if let number = countNumber {
            guard commentText == nil else {
                throw DecodeError.moreThanOneEnumCase
            }
            return .count(number: number)
        }
        if let text = commentText {
            guard countNumber == nil else {
                throw DecodeError.moreThanOneEnumCase
            }
            return .comment(text: text)
        }
        throw DecodeError.noRecognizedContent
    }

    enum DecodeError: Error {
        case noRecognizedContent
        case moreThanOneEnumCase
    }
}

let test = PostType.count(number: 3)
let data = try JSONEncoder().encode(test)
let string = String(data: data, encoding: .utf8)!
print(string) // {"countNumber":3}
let result = try JSONDecoder().decode(PostType.self, from: data)
print(result) // count(3)

এটি বেশ সহজ, কেবল String বা Int কাঁচা মানগুলি ব্যবহার করুন যা নিখুঁতভাবে বরাদ্দ করা হয়েছে।

enum PostType: Int, Codable {
    case image, blob
}

image 0 এ এনকোড করা হয়েছে এবং 1 blob হয়

অথবা

enum PostType: String, Codable {
    case image, blob
}

image "image" এ এনকোড করা হয়েছে এবং "blob"

এটি কীভাবে ব্যবহার করবেন এটি এটি সাধারণ উদাহরণ:

enum PostType : Int, Codable {
    case count = 4
}

struct Post : Codable {
    var type : PostType
}

let jsonString = "{\"type\": 4}"

let jsonData = Data(jsonString.utf8)

do {
    let decoded = try JSONDecoder().decode(Post.self, from: jsonData)
    print("decoded:", decoded.type)
} catch {
    print(error)
}

যদি অজানা .dataCorrupted মুখোমুখি হয় তবে সুইফট একটি .dataCorrupted ত্রুটি .dataCorrupted । যদি আপনার ডেটা কোনও সার্ভার থেকে আসে, তবে এটি আপনাকে যে কোনও সময় একটি অজানা এনাম মান প্রেরণ করতে পারে (বাগ সার্ভার সাইড, নতুন এপিআই সংস্করণে যুক্ত করা এবং আপনি আপনার অ্যাপ্লিকেশনটির পূর্ববর্তী সংস্করণগুলি কৃপণুভাবে পরিচালনা করতে পারেন ইত্যাদি), আপনার এনামগুলিকে নিরাপদে ডিকোড করার জন্য আপনি আরও ভাল প্রস্তুত এবং কোড "ডিফেন্সিভ স্টাইল" রাখতে চান।

এটি কীভাবে করা যায় তার সাথে সম্পর্কিত মান সহ বা ছাড়াই এখানে একটি উদাহরণ

    enum MediaType: Decodable {
       case audio
       case multipleChoice
       case other
       // case other(String) -> we could also parametrise the enum like that

       init(from decoder: Decoder) throws {
          let label = try decoder.singleValueContainer().decode(String.self)
          switch label {
             case "AUDIO": self = .audio
             case "MULTIPLE_CHOICES": self = .multipleChoice
             default: self = .other
             // default: self = .other(label)
          }
       }
    }

এবং এটি কীভাবে একটি সংযুক্তি কাঠামোতে ব্যবহার করবেন:

    struct Question {
       [...]
       let type: MediaType

       enum CodingKeys: String, CodingKey {
          [...]
          case type = "type"
       }


   extension Question: Decodable {
      init(from decoder: Decoder) throws {
         let container = try decoder.container(keyedBy: CodingKeys.self)
         [...]
         type = try container.decode(MediaType.self, forKey: .type)
      }
   }




enums