2010-02-26 15 views
20

ObjectiveC'de ... ile ilgili bazı sorunlar.Objective-C etrafında geçen ... nil sonlandırılmış bağımsız değişken listeleri

Temelde bir yöntem sararak ve nil sonlandırılmış listesini kabul eder ve doğrudan ben sarma ediyorum yönteme aynı listeyi geçmek istiyorum ediyorum.

İşte sahip olduğum şey ancak EXC_BAD_ACCESS çökmesine neden oluyor. otherButtonTitles sadece bunu basitçe nasıl aynı nil sonlandırıldı listeyi koruyarak argüman gelen giden argüman, gelen sifon yok otherButtonTitles:@"Foo", nil]

+ (void)showWithTitle:(NSString *)title 
       message:(NSString *)message 
      delegate:(id)delegate 
    cancelButtonTitle:(NSString *)cancelButtonTitle 
    otherButtonTitles:(NSString *)otherButtonTitles, ... 
{ 
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title 
                message:message 
                delegate:delegate 
              cancelButtonTitle:cancelButtonTitle 
              otherButtonTitles:otherButtonTitles] autorelease]; 
    [alert show]; 
} 

ile geçirilen bir NSString olduğunda yerel değişkenler incelenmesi, göründüğü?

+1

variadic yöntem listedeki ilk nesne bir NSString olarak otherButtonTitles bakın neden va_list kendisinin bir parçası değildir. Yani, va_list sadece "..." bölümündeki nesneleri içerir. – Don

+1

Objective-C, C'nin bir üst kümesidir, cf. http://stackoverflow.com/questions/150543/forward-an-invocation-of-a-variadic-function-in-c. – Don

cevap

40

Bunu yapamazsınız, en azından bunu yapmak istediğiniz şekilde yapamazsınız. Ne yapmak istediğiniz (değişken bağımsız değişkenleri iletmek), UIAlertView üzerinde bir va_list kabul eden bir başlatıcıya sahip olmayı gerektirir. Bir tane yok.

+ (void)showWithTitle:(NSString *)title 
       message:(NSString *)message 
      delegate:(id)delegate 
    cancelButtonTitle:(NSString *)cancelButtonTitle 
    otherButtonTitles:(NSString *)otherButtonTitles, ... 
{ 
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title 
                message:message 
                delegate:delegate 
              cancelButtonTitle:cancelButtonTitle 
              otherButtonTitles:nil] autorelease]; 
    if (otherButtonTitles != nil) { 
     [alert addButtonWithTitle:otherButtonTitles]; 
     va_list args; 
     va_start(args, otherButtonTitles); 
     NSString * title = nil; 
     while(title = va_arg(args,NSString*)) { 
      [alert addButtonWithTitle:title]; 
     } 
     va_end(args); 
    } 

    [alert show]; 
} 

Bu, tabii ki, çok sorun özgü: Ancak, addButtonWithTitle: yöntemi kullanabilirsiniz. Asıl cevap "değişken argüman listesini dolaylı olarak va_list parametresine sahip olmayan bir yönteme/işleve geçiremezsiniz". Bu nedenle sorun etrafında bir yol bulmalısınız. Verdiğiniz örnekte, ilettiğiniz başlıkları içeren bir uyarı yapmak istediniz. Neyse ki sizin için UIAlertView sınıfı, yinelemeli olarak düğmelere ekleyebileceğiniz ve böylece genel olarak aynı etkiyi elde edebileceğiniz bir yönteme sahiptir. Bu yönteme sahip olmasaydı, şansın kalmazdı.

Diğer gerçekten dağınık seçenek onu değişken bir makro yapmak olabilir. Bir variadic makro şuna benzer: Ancak

#define SHOW_ALERT(title,msg,del,cancel,other,...) { \ 
    UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; \ 
    [_alert show]; \ 
} 

, hatta variadic makro yaklaşımla, yine de bunu yapmak istedim her zaman için özel bir makro gerekiyordu. Bu çok katı bir alternatif değil.

+1

Serin bir yaklaşım, ama bu tekniği argüman listesi ile yardımcı olmak için böyle bir yöntemin bulunmadığı başka yerlerde kullanmayı umuyordum. Nil sonlandırılmış bir listeyi dinamik olarak oluşturmanın gerçekten bir yolu yok mu? –

+0

@Squeegy belki bir "va_list" sahte olabilirsiniz (@ Don'un yorumunda cocoawithlove bağlantısına bakınız), ancak çağırmak istediğiniz yöntem bir "va_list" ("...' "nin tersi) almıyorsa, kullanamazsınız o. –

+0

Neyse ki, Dave'in çözümü özel durumunuz için çalışıyor. – Don

0

NSInvocation nesnesini oluşturma hakkında ne düşünüyorsunuz? Argümanlar işaretçi tarafından geçirilmesi gerektiğinden, işaretçiyi nil sonlandırılmış listesine geçirebilirsiniz.

Ayrıca marg_list() kullanarak parametreler üzerinde yineleme yapabilir ve kendiniz bir sonlandırılmış liste oluşturabilirsiniz.

Bunlar sadece basit önerilerdir; Onları denemedim.

+0

"NSInvocation", değişken sayıdaki argüman veya "union" argümanlarıyla yöntemlerin çağrılmasını desteklemez. " - http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html#//apple_ref/doc/uid/20000212-1804 –

+0

Bu, bunu öldürür. öneri! – Don

+0

Sanırım bu gibi bir şeyleri listeleyebilirim: http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D ama 'marg_list() 'i nasıl kullanabilirim? Dinamik olarak bir tane üretmek için geri dönebilirim. –

0

Bu yalnızca -iOS7 üzerinde OP'ın UIAlertView -paketleme ve dozaj duruma özgü ve test edilmiştir: Bir UIAlertViewUIAlertViewStylePlainTextInput onun tarzı belirledi ardından otherButtons:nil ile başlatılır ve bir kez onun temsilcisi en alertViewShouldEnableFirstOtherButton: çağrısı bulunmadığını tespit ettik girişi doğrula. Bunun bir hata mı yoksa amaçlanmış bir davranış mı olduğundan emin değilim ama en az şaşkınlık ilkemi kırdı.

UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Title" 
              message:@"message" 
              delegate:self   
            cancelButtonTitle:@"Cancel" 
            otherButtonTitles:nil]; 
[av setAlertViewStyle:UIAlertViewStylePlainTextInput]; 
[av addButtonWithTitle:@"OK"]; 
[av show]; 

çözümü UIAlertView mutlu otherButtons:nil kabul beri, otherButtonTitles ile UIAlertView (sıfır olabilir) sıfırlayabilirsiniz ve üzerinde yineleme şudur: Bu (ı temsilci en alertViewShouldEnableFirstOtherButton: uygulanmaktadır varsayıyoruz) Aşağıdaki ile tekrarlanabilir olduğu yukarıdaki gibi variadic argümanlar,:

+ (void)showWithTitle:(NSString *)title 
       message:(NSString *)message 
      delegate:(id)delegate 
    cancelButtonTitle:(NSString *)cancelButtonTitle 
    otherButtonTitles:(NSString *)otherButtonTitles, ... 
{ 
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title 
                message:message 
                delegate:delegate 
              cancelButtonTitle:cancelButtonTitle 
              otherButtonTitles:otherButtonTitles] autorelease]; 

    // add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here 

    if (otherButtonTitles != nil) { 
     va_list args; 
     va_start(args, otherButtonTitles); 
     NSString * title = nil; 
     while(title = va_arg(args,NSString*)) { 
      [alert addButtonWithTitle:title]; 
     } 
     va_end(args); 
    } 

    [alert show]; 
} 
+0

Bu ilginç bir bilgidir ve kesinlikle Apple'ın [hata muhabiri] (http://bugreport.apple.com/) adresinde bildirilmelidir, ancak bu yazının cevabı değildir. Anladığım kadarıyla, sorulan soruya ek bilgi sağlamaz. –

+0

Zaten rapor edildi. Katılıyorum, kısmen; Google'ın, kendimden oluşan değişken bir UIAlertView ambalajıyla uğraşırken bana getirdiği yerdeki kabul edilen yanıtın bir düzeltmesi. Belki başka birine yardım eder ... –

İlgili konular