Kodlanabilir: Yanlış Enum Değerlerini İşleme
Kod tabanınızı koruma: beklenmedik numaralandırma değerleriyle uğraşma
Uygulamanızın birdenbire çökmeye başladığı bir durumla hiç karşılaştınız mı? Bu durum, araştırma sonucunda arka ucun, kodda enum içinde bulunmayan belirli bir enum tabanlı alan için bir değer sağladığını ortaya çıkardı?
Aşağıdaki örneği göz önünde bulundurun:
import Foundation
struct Person: Codable {
let name: String
let favouriteBeverage: Beverage
}
enum Beverage: String, Codable {
case Tea
case Coffee
}
let jsonString = """
{
"name": "Shubham Bakshi",
"favouriteBeverage": "Tea"
}
""".data(using: .utf8)!
let decodedJSON = try! JSONDecoder().decode(Person.self, from: jsonString)
switch decodedJSON.favouriteBeverage {
case .Tea:
print("Ohhh I love some Tea")
case .Coffee:
print("Coffee is no Tea but meh, I'll take it")
}
Ohhh biraz çay severim
favouriteBeverage
Ancak JSON verilerini Tea yerine Juice ( enum içinde olmayan bir değer olan Beverage ) olarak değiştirirsek ne olur ?
let jsonString = """
{
"name": "Shubham Bakshi",
"favouriteBeverage": "Juice"
}
""".data(using: .utf8)!
Mesajın şu kısmına odaklanın: "Geçersiz Dize değerinden İçecek başlatılamıyor Meyve Suyu"
Bir oyun alanı kodu yerine gerçek bir uygulama olsaydı, uygulama çökerdi. Öyleyse, arka uç yanıtta geçersiz bir değer gönderse bile, uygulamamızın tamamen çökmek yerine bunu işleyebilmesi gerçeğini nasıl halledeceğiz ?
Yollardan biri ve benim kişisel favorim: Yanlış Numaralandırma Geri Dönüş Mekanizması.
Mekanizma diyor ama aşağı yukarı her şeyi halleden bir protokol. İşte başlıyoruz….
/// This is useful in case the backend specifies some value that does not
/// exist inside the enum as in such cases the app crashes since it fails to
/// parse the enum.
///
/// This ensures that in case an invalid value is specified, the app will
/// not crash but rather resort to a value specified for
/// `fallbackForIncorrectEnumValue`
///
protocol IncorrectEnumFallbackMechanism: RawRepresentable, Codable {
/// Fallback value in case the backend returns an incorrect value for
/// the enum
static var fallbackForIncorrectEnumValue: Self { get }
}
extension IncorrectEnumFallbackMechanism where RawValue: Codable {
init(from decoder: Decoder) throws {
// Fetching the value specified inside the JSON
let value = try decoder.singleValueContainer().decode(RawValue.self)
// Creating the instance based on the provided value or falling back
// to a default value in case the provided value for creating is
// invalid
self = Self(rawValue: value) ?? Self.fallbackForIncorrectEnumValue
}
/// Since `RawRepresentable` declares a `encode(coder:)` by default so we
/// don't need to implement that explicitly
}
enum Beverage: String, IncorrectEnumFallbackMechanism {
static var fallbackForIncorrectEnumValue: Beverage = .SomeWeirdBeverage
case Tea
case Coffee
case SomeWeirdBeverage
}
Beklemek! Bu nedir?
Arka uç bize favouriteBeverage
.
Yani tam kodumuz şimdi şöyle görünecek:
import Foundation
/// This is useful in case the backend specifies some value that does not
/// exist inside the enum as in such cases the app crashes since it fails to
/// parse the enum.
///
/// This ensures that in case an invalid value is specified, the app will
/// not crash but rather resort to a value specified for
/// `fallbackForIncorrectEnumValue`
///
protocol IncorrectEnumFallbackMechanism: RawRepresentable, Codable {
/// Fallback value in case the backend returns an incorrect value for
/// the enum
static var fallbackForIncorrectEnumValue: Self { get }
}
extension IncorrectEnumFallbackMechanism where RawValue: Codable {
init(from decoder: Decoder) throws {
// Fetching the value specified inside the JSON
let value = try decoder.singleValueContainer().decode(RawValue.self)
// Creating the instance based on the provided value or falling back
// to a default value in case the provided value for creating is
// invalid
self = Self(rawValue: value) ?? Self.fallbackForIncorrectEnumValue
}
/// Since `RawRepresentable` declares a `encode(coder:)` by default so we
/// don't need to implement that explicitly
}
struct Person: Codable {
let name: String
let favouriteBeverage: Beverage
}
enum Beverage: String, IncorrectEnumFallbackMechanism {
static var fallbackForIncorrectEnumValue: Beverage = .SomeWeirdBeverage
case Tea
case Coffee
case SomeWeirdBeverage
}
let jsonString = """
{
"name": "Shubham Bakshi",
"favouriteBeverage": "Juice"
}
""".data(using: .utf8)!
let decodedJSON = try! JSONDecoder().decode(Person.self, from: jsonString)
switch decodedJSON.favouriteBeverage {
case .Tea:
print("Ohhh I love some Tea")
case .Coffee:
print("Coffee is no Tea but meh, I'll take it")
case .SomeWeirdBeverage:
print("Wait! What is that?")
}
İşte bu millet! Mutlu Kodlama!
Benimle LinkedIn üzerinden iletişime geçebilir veya diğer kanallardan benimle iletişime geçebilirsiniz.