Aslında NSAssert'in anlamı nedir?


155

Bunu sormak zorundayım, çünkü: Tanıma ettiğim tek şey, iddianın başarısız olması durumunda uygulamanın çökmesidir. NSAssert kullanmanın nedeni bu mu? Ya da bunun yararı nedir? Ve bir NSAssert'i kodda yaptığım herhangi bir varsayımın hemen üstüne koymak doğru mudur? Param olarak asla -1 almaması gereken bir işlev gibi -0.9 veya -1.1 olabilir mi?

Yanıtlar:


300

Assert, bir değerin olması gereken şey olduğundan emin olmaktır. Bir onaylama başarısız olursa, bir şey ters gitti demektir ve bu nedenle uygulama kapanır. Assert kullanmanın bir nedeni, davranıştan geçmeyecek veya çok kötü yan etkiler yaratacak bir işleve sahipseniz, kendisine iletilen parametrelerden biri tam olarak bir değer değilse (veya bir değer aralığı) olabilir. Bu değerin olmasını beklediğiniz değer olduğundan emin olun ve eğer değilse o zaman bir şey gerçekten yanlıştır ve bu yüzden uygulama kapanır. Assert, hata ayıklama / birim testi için ve ayrıca kullanıcıların "kötü" şeyleri yapmasını durdurmak için çerçeveler sağladığınızda çok yararlı olabilir.


9
Serbest bırakmak için NSAssert'i çıkarmalısınız. Bunu yapmak için bir derleme zamanı bayrağı var.
Barry Wark

127
> Serbest bırakmak için NSAssert'i çıkarmalısınız. Bu tartışmalıdır. Uygulamalarımı her zaman onaylar etkin olarak yayınlıyorum ve bu birçok yazılım için standart bir uygulamadır, örneğin Apple bunu yapar. Programınız anormal bir durum tespit ettiği anda çökmeniz gerekir. Hatanın oluştuğu yerin yığın izlemesini alabilirsiniz, ancak iddiaları devre dışı bırakırsanız, bellek ve / veya kullanıcı verilerini bozabilir ve sorunun hatalarını ayıklamak çok zor olacaktır.
Mike Weller

18
XCode 4'ün sürüm yapılandırmalarında varsayılan olarak tanımlanmış NS_BLOCK_ASSERTIONS olduğunu unutmayın. Sanırım yayınlanan kodunuzun NSAssert: s içermeyeceğini değiştirmezseniz.
Jonny

16
Doğru anlarsam, onları bırakmanın anlamı nedir (yayın sürümünde)? NSAssert'i neden bir if ifadesiyle değiştirmiyorsunuz ve eğer (korkunç bir şey olursa), kullanıcıyı bilgilendirin (veya kontrolünüz altındaki bir şeyi yapın ) ve sadece çıkın / çökmeyin ve kullanıcıyı ne olduğunu merak etmeyin ... bir şey mi kaçırıyorum?
Gik

11
Normal şartlar altında olması gerekmeyen her istisnai durumun yolunu bulmak geliştiricinin zamanını boşa harcıyor. Bu, kullanıcıyı her biri için bilgilendirmek için uygun yolların düşünülmesini ve / veya uygulamanın, oluştuktan sonra beklenen bir şekilde devam edecek kadar sağlam olmasını içerir. Daha pratik yaklaşım, uygulamayı kilitlemek ve kilitlenme raporunda bulunan hatayı düzeltmek ve yeni bir sürüm yayınlamaktır. Bunu söyledikten sonra, böyle bir durumda veri kaybının olmadığından emin olmak önemlidir. Yine de bu sağlanmalıdır, ancak çok daha az iştir.
trss

20

NSAssert ile gerçekten konuşamıyorum, ancak C'nin iddialarına () benzer şekilde çalıştığını hayal ediyorum.

assert (), kodunuzda anlamsal bir sözleşme uygulamak için kullanılır. Ne demek istiyorsun?

Dediğiniz gibi: Asla -1 almamanız gereken bir fonksiyonunuz varsa, assert () uygulamanızı şu şekilde uygulayabilirsiniz:

void gimme_positive_ints (int i) {
  iddia (i> 0);
}

Ve şimdi hata günlüğünde (veya STDERR) böyle bir şey göreceksiniz:

Onay i> 0 başarısız oldu: file.c dosyası, satır 2

Bu yüzden sadece potansiyel olarak kötü girişlere karşı güvenli bir koruma sağlamakla kalmaz, aynı zamanda bunları kullanışlı ve standart bir şekilde kaydeder.

Oh, ve en azından C assert () içinde bir makro vardı, bu yüzden assert () öğesini sürüm kodunuzda hayır olarak yeniden tanımlayabilirsiniz. NSAssert (ya da daha fazla iddia ()) ile durum böyle olup olmadığını bilmiyorum, ama bu kontrolleri derlemek oldukça yararlı oldu.


2
Evet, NSAssert de bir makro.
Martin Wickman

18

NSAssertsize sadece uygulama çökmesini daha verir. Sınıfı, yöntemi ve iddianın gerçekleştiği satırı size söyler. Tüm iddialar NS_BLOCK_ASSERTIONS kullanılarak kolayca devre dışı bırakılabilir. Böylece hata ayıklama için daha uygun hale getirilir. Öte yandan, NSExceptionsadece atma uygulaması çöküyor. Ayrıca istisnanın yeri hakkında bilgi vermez ve bu kadar basit bir şekilde devre dışı bırakılamaz. Aşağıdaki resimlerdeki farka bakın.

NSAssert belgelerinde belirtildiği gibi bir iddia da istisna oluşturduğundan uygulama kilitleniyor :

Çağrıldığında, bir onaylama işleyicisi yöntem ve sınıf adlarını (veya işlev adını) içeren bir hata iletisi yazdırır. Daha sonra bir NSInternalInconsistencyException özel durumu oluşturur.

NSAssert:

Bir iddianın ardından günlükler

NSException:

İstisnadan sonraki günlükler


A NSException, reasonve userInfoparametreleri aracılığıyla döndürdüğü çıktıyı özelleştirmek için bolca fırsat sağlar . Sınıf adı, seçici, satır bilgileri ve hata ayıklamaya yardımcı olması için eklemeyi düşündüğünüz başka bir şey ekleyememenizin hiçbir nedeni yoktur. IMHO, NSAssertgeliştirme sırasında hata ayıklama amacıyla bir kullanırsınız, ancak gönderilmesini devre dışı bırakırsınız ; NSExceptionGönderim kodunda bir iddiada bırakmak istiyorsanız bir atarsınız .
markeissler

17

Herkesin yukarıda söylediklerinin dışında, NSAssert()(C'lerin aksine assert()) varsayılan davranışı , yakalayabileceğiniz ve işleyebileceğiniz bir istisna atmaktır. Örneğin, Xcode bunu yapar.


İstisnayı nasıl yakalayıp ele alabileceğimiz hakkında daha fazlası var mı?
Aralık'ta Gon

1
Kakao istisnaları fiili "catchable ve handleable" DEĞİLDİR. Denetim, arama ağacının herhangi bir yerinde bir elma işlevinden geçerse, davranış tanımsızdır. İstisnalar yalnızca Java'da olduğu gibi genel kullanım için değil, yalnızca hata raporlaması içindir (aka, yaratıkçılık vb.).
Michael

9

Sadece belirtildiği gibi, ancak tam olarak açıklanmadığı gibi, sadece özel kod oluşturmak (örneğin ifs yapmak ve kötü veriler için bir istisna oluşturmak) yerine iddialara sahip olmak ve kullanmak için neden, üretim uygulamaları için devre dışı bırakılmalıdır.

Geliştirme ve hata ayıklama sırasında, hatalar yakalamanız için öneriler etkinleştirilir. Bir iddia yanlış olarak değerlendirildiğinde program durur. Ancak, üretim için derleme yaparken, derleyici onaylama kodunu atlar ve aslında PROGRAM ÇALIŞMASINI DAHA HIZLI YAP. O zamana kadar, umarım, tüm hataları düzelttiniz. Programınızın üretim sırasında hala hataları olması durumunda (iddialar devre dışı bırakıldığında ve program iddiaları "atladığında", programınız muhtemelen başka bir noktada kilitlenecektir.

NSAssert'in yardımından: "NS_BLOCK_ASSERTIONS önişlemci makrosu tanımlanmışsa, bildirimler devre dışı bırakılır." Yani, makroyu sadece dağıtım hedefinize koyun [sadece].


6

NSAssert(ve stdlib eşdeğeri assert) geliştirme sırasında programlama hatalarını tespit etmektir. Bir üretim (serbest bırakma) uygulamasında başarısız olan hiçbir iddiaya sahip olmamalısınız. Dolayısıyla, pozitif bir argüman gerektiren bir yönteme asla negatif bir sayı iletmediğinizi iddia edebilirsiniz. Test sırasında iddia hiç başarısız olursa, bir hata var. Bununla birlikte, iletilen değer kullanıcı tarafından girilirse, üretimdeki iddiayı kullanmak yerine girdinin doğru bir şekilde doğrulanması gerekir (devre dışı bırakılan sürüm derlemeleri için bir #define ayarlayabilirsiniz NSAssert*.


2
+1 çünkü cevabınız benim için en anlamlı! NSAssert kullanımı, serbest bırakıldıktan sonra değil, geliştirme amaçlıysa daha mantıklıdır. İzin verilmeyen bir değer giren bir kullanıcının ardından NSAssert uygulamasının çökmesine değil, bir UI hatası gelmelidir. Sis temizlendi!
pnizzle

3

İddialar, belirli bir yöntemin veya mantığın bir parçasının amaçlanan kullanımını zorlamak için yaygın olarak kullanılır. Diyelim ki sıfırdan büyük iki tamsayının toplamını hesaplayan bir yöntem yazıyorsunuz. Yöntemin her zaman amaçlandığı gibi kullanıldığından emin olmak için, muhtemelen bu durumu test eden bir iddia koyabilirsiniz.

Kısa cevap: Kodunuzun yalnızca amaçlandığı gibi kullanılmasını zorunlu kılarlar.



2

Sorusunu tam olarak cevaplamak için, herhangi bir iddia türünün amacı hata ayıklamaya yardımcı olmaktır. Hataları kaynağında yakalamak, çökmelere neden olduklarında hata ayıklayıcıda yakalamak daha değerlidir.

Örneğin, belirli bir aralıktaki değerleri bekleyen bir işleve bir değer iletebilirsiniz. İşlev, değeri daha sonra kullanmak üzere saklayabilir ve daha sonra uygulama çöküyor. Bu senaryoda görülen çağrı yığını, kötü değerin kaynağını göstermez. Kötü değeri kimin geçtiğini ve nedenini bulmak için kötü değeri yakalamak daha iyidir.


-3

NSAssertkoşulla eşleştiğinde uygulama çökmesi yapın. Koşulla eşleşmezse, sonraki ifadeler yürütülür. Aşağıdaki EX'i arayın:

Ben sadece görevi nedir test etmek için bir uygulama oluşturmak NSAssert:

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testingFunction:2];
}

-(void)testingFunction: (int)anNum{
    // if anNum < 2 -> the app will crash
    // and the NSLog statement will not execute
    // that mean you cannot see the string: "This statement will execute when anNum < 2"
    // into the log console window of Xcode
    NSAssert(anNum >= 2, @"number you enter less than 2");
    // If anNum >= 2 -> the app will not crash and the below 
    // statement will execute
    NSLog(@"This statement will execute when anNum < 2");
}

benim kod içine uygulama çökmez.Ve test durumda:

  • anNum > = 2 -> Uygulama çökmeyecek ve günlük dizesini görebilirsiniz: "Bu ifade, anNum <2 olduğunda outPut günlük konsolu penceresine yürütülür
  • anNum <2 -> Uygulama çökecek ve günlük dizesini göremiyorsunuz: "anNum <2 olduğunda bu ifade çalıştırılacaktır"

1
Sen başka türlü var. Msgstr "NSAssert, koşulla eşleştiğinde uygulama kilitlenmesine neden olur. Koşulla eşleşmezse sonraki ifadeler yürütülür". NSAssert, koşulla eşleşmezse uygulamayı kilitler ve koşulla eşleşirse normal olarak yürütür.
Joe Tam

Uygulama, koşulu karşılamadığında çöküyor ve günlüğe kaydediliyor, aksi takdirde daha fazla yürütüyor.
Pravin S.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.