2010-07-13 21 views
5

Güvenli bir döküm gerçekleştirmek için Objective-C'ye bir makro yazdım. Bu gerçekten iyi çalışıyorAmaç-C Güvenli Döküm Makrosu

#define SAFE_CAST(OBJECT, TYPE) ([OBJECT isKindOfClass:[TYPE class]] ? (TYPE *) OBJECT: nil) 

, ancak iki kez adlı vermedi böylece bir değişkende OBJECT saklamak için bir yol olsaydı iyi olurdu: Burada şimdiye kadar böyle görünüyor. Makro genişletildiğinde buna benzer kod

NSString *str = SAFE_CAST([dictinary objectForKey:key], NSString); 

sonuçları: Örneğin, gibi makro kullanarak

:

NSString *str = ([[dictinary objectForKey:key] isKindOfClass:[NSString class]] ? (NSString *) [dictinary objectForKey:key]: nil); 

daha böyle çalışması için tercih ediyorum

id obj = [dictionary objectForKey:key]; 
NSString *str = ([obj objectForKey:key] isKindOfClass[NSString class]] ? (NSString *) obj : nil); 

Teşekkürler.

+0

ben bu noktanın ne görmüyorum. Bunu plisten sterilize etmek için kullanmak istediğini söyledin, ama eğer bunu kullanırsan, iade edilen nesnenin sıfır olup olmadığını test etmelisin? Neden sadece nesne KindOfClass: expectedClass olup olmadığını test etmiyor? – JeremyP

cevap

8

Sen bunu SAFE_CAST kullanmayı çok gereken bir durum var genellikle kötü bir yaklaşım olduğunu düşünüyorum dedi

#define SAFE_CAST(OBJECT, TYPE) ({ id obj=OBJECT;[obj isKindOfClass:[TYPE class]] ? (TYPE *) obj: nil; }) 

olması deyimi statement expressions adında bir GCC uzantısını kullanabilirsiniz. Hiçbir zaman bir diziye farklı sınıf nesneleri koymak; Farklı sınıfların UI nesneleri için hiçbir zaman (IBAction)someAction:(id)sender eylem mesajını tekrar kullanmayın. O zaman genellikle SAFE_CAST'u kullanmanız gerekmez.

+1

Şu an bir makrodan bilgi okurken bu makroyu kullanıyorum. Poliçenin içeriği geçerli olduğundan emin değilim. Diğer oyuncular gibi; istismar edilebilir, ancak kullanımları vardır. Bunu yapmanın daha iyi bir yolu varsa, lütfen detaylandırır mısınız? Cevabınıza göre ifade ifadeleri ilginç görünüyor. LLVM ile kullanılabilir mi? – LandonSchropp

+0

Evet, "clang" ile çalışır. "Plist" için, kullanıcı tarafından sağlanmışsa, SAFE_CAST işlevini kullanmayı kabul ediyorum. Ama eğer değilse, geliştirirken 'NSAssert' kullanmanın daha iyi olacağını düşünüyorum, böylece geçersiz bir plist hazırladığımda programın çökmesi; Uygulamanızın sürüm oluşturma özelliği, "plFE" nin geçerli olduğundan emin olmanız için "SAFE_CAST" gerektirmemelidir. – Yuji

+0

Harika çalışıyor. Teşekkürler. – LandonSchropp

0

Öyleyse böyle yazın, sadece {} while (0) < - ve parantez içinde değil.

#define SAFE_CAST(OBJECT, TYPE, VAR) do { \ 
    id obj = OBJECT; \ 
    VAR = [obj isKindOfClass:[TYPE class]] ? (TYPE *) obj : nil; \ 
} while(0) 
+0

Yukarıda kullandığım kullanımda doğru şekilde derlemek için bunu alamıyorum. Derleyici çıktıları: hata: 'önce' beklenen ifade. – LandonSchropp

+0

Err, haklısın üzgünüm. İlk önce, nil'den sonra bir sözdizimi hatası var; ve ikincisi, kendi başına kalması gerekiyor. Anlam, üçlü işlemin çıktılarını atayan ya da farklı bir şekilde yapan başka bir argümandan geçer. :) – jer

+0

Endişeye gerek yok. Yine de cevap için teşekkürler. – LandonSchropp

4

Gerçekten bunu yapmalısınız düşünüyorsanız, bir işlev kullanabilirsiniz:

#define SAFE_CAST(Object, Type) (Type *)cast_helper(Object, [Type class]) 
static id cast_helper(id x, Class c) { 
    return [x isKindOfClass:c] ? x : nil; 
} 
+0

Bu ilginç bir yaklaşım, ancak bir makro sadece biraz daha temiz görünüyordu. Küresel fonksiyonlara sahip olmamaya çalışıyorum. Ayrıca, 'Bunu yapman gerektiğini gerçekten düşünüyorsan' ile ne demek istediğini açıklayabilir misiniz?Diğer birçok dil C# ve C++ dahil olmak üzere güvenli döküm desteği. Neden onları kullanmamalıyım? – LandonSchropp

+1

@helixed: Neden etrafta asılı duran küresel bir makronun etrafta asılı bir küresel işlevden daha iyi olduğunu düşünüyorsunuz? – JeremyP

+0

@helixed: Yukarıda bahsedilen plist yaklaşımı için, bu dinamik kalıpların gerçekten ihtiyaç duyduğu durum nadirdir. Global problemle ilgili problemi görmüyorum - sadece düz ileri metin işlemeyi yapan makrolardan ziyade işlevleri kullanıyorum. –