Pertanyaan Bagaimana cara menghilangkan blok Objective-C @try @catch seperti ini?


Saya seorang pengembang dari dunia Python digunakan untuk menggunakan pengecualian. Saya menemukan di banyak tempat bahwa menggunakan pengecualian tidak begitu bijaksana di sini, dan melakukan yang terbaik untuk mengonversi ke NSErrors saat diperlukan. tetapi kemudian saya menemukan ini:

NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
    // Memory management code omitted
    SomeModel *model = [[SomeModel alloc] init];
    model.attr1 = [[dict objectForKey:@"key1"] integerValue];
    model.attr2 = [[dict objectForKey:@"key2"] integerValue];
    model.attr3 = [[dict objectForKey:@"key3"] integerValue];
    model.attr4 = [[dict objectForKey:@"key4"] integerValue];

    [results addObject:model];
}

dengan beberapa objek dict yang berisi NSNull, yang akan menghasilkan pengecualian "pemilih yang tidak dikenal". Dalam hal ini, saya ingin menjatuhkan datum itu sepenuhnya. Naluri pertama saya adalah untuk membungkus seluruh konten dari blok tersebut menjadi blok @ try- @ catch:

NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
    @try
    {
        SomeModel *model = [[SomeModel alloc] init];
        model.attr1 = [[dict objectForKey:@"key1"] integerValue];
        model.attr2 = [[dict objectForKey:@"key2"] integerValue];
        model.attr3 = [[dict objectForKey:@"key3"] integerValue];
        model.attr4 = [[dict objectForKey:@"key4"] integerValue];

        [results addObject:model];
    }
    @catch(NSException *exception)
    {
        // Do something
    }
}

Tetapi apakah ini pendekatan yang baik? Saya tidak dapat menemukan solusi tanpa mengulangi pemeriksaan pada setiap variabel, yang benar-benar jelek IMO. Mudah-mudahan ada alternatif lain yang tidak pernah terjadi pada saya. Terima kasih sebelumnya.


4
2017-10-31 10:13


asal


Jawaban:


Banyak orang menggunakan kategori pada NSDictionary untuk kasus-kasus ini:

- (id)safeObjectForKey:(id)aKey
{
  id obj = [self objectForKey:aKey];
  if ([obj isKindOfClass:[NSNull class]])
  {
    return nil;
  }

  return obj;
}

Anda masih perlu memastikan, bahwa dikt Anda adalah contoh kamus yang sebenarnya.


1
2017-10-31 11:03



Cara Objective-C yang tepat untuk melakukan ini adalah:

for (NSDictionary *dict in dicts)
{
    if (! [dict isKindOfClass:[NSDictionary class]])
        continue;
    // ...
}

Menguji apakah penerima dapat menanggapi pesan sebelum mengirimnya adalah pola umum di Objective-C.

Juga, perhatikan bahwa pengecualian dalam Objective-C selalu kesalahan programmer dan tidak digunakan untuk aliran eksekusi normal.


3
2017-10-31 10:18



Pada akhirnya saya memutuskan untuk menyelesaikan masalah menggunakan KVC. Sesuatu seperti ini:

- (id)initWithPropertyDictionary:(NSDictionary *)dict
                     lookUpTable:(NSDictionary *)keyToProperty
{
    self = [self init];
    for (NSString *key in dict)
    {
        NSString *propertyName;
        if ([keyToProperty objectForKey:key])
            propertyName = [keyToProperty objectForKey:key];
        else
            propertyName = key;
        if ([[dict objectForKey:key] isKindOfClass:[NSNull class]])
        {
            [self release];
            return nil;
        }
        else
        {
            [self setValue:[dict objectForKey:key] forKey:propertyName];
        }
    }
}

Kemunduran resolusi ini adalah bahwa saya harus menggunakan NSNumber untuk properti saya, tetapi untuk data JSON benar-benar tidak ada perbedaan antara bilangan mengambang dan bilangan bulat, jadi ini baik-baik saja.

Dan jika Anda benar-benar menginginkan tipe primitif, Anda bisa menggabungkan metode ini dengan setter khusus yang mengubah NSNumbers menjadi tipe yang sesuai.

Dengan ini, semua yang perlu Anda lakukan adalah memeriksa nihil sebelum menambahkan objek ke dalam array. Jauh lebih bersih di mana-mana kecuali kelas model.

Terima kasih kepada jaydee3 karena telah mengilhami saya untuk fokus mengubah kelas model.


0
2017-11-02 06:52