2016-04-04 17 views
0

Vücudunda bir Objective-C bloğu dışında bulunan çeşitli değişkenleri değiştirmek istiyorum.Nesne-C bloklarında parametreleri değiştirin

Değişkeni bildirirken, __block özniteliğini kullanarak bir değişkene doğrudan erişip değiştirebileceğimi biliyorum. Yani bu çalışır:

__block NSMutableString *alertMessage; 

void(^appendMessage)(NSMutableString*, NSString*)= ^(NSString *append){ 

    if (!alertMessage) 
    { 
     alertMessage = [NSMutableString new]; 
    } 

    if ([append length] > 0) 
    { 
     [alertMessage appendString:@"\n"]; 
    } 

    [alertMessage appendString:append]; 
}; 

appendMessage(@"Alert part 1"); //This works fine 

Ancak bana doğrudan aynı erişmeden blok dışında çok sayıda değişkeni temel operasyon kullanımı sağlayan bir geçti değişken üzerinde bir işlem gerçekleştirebilen bir blok oluşturmak istiyorum. Aşağıdaki gibi bir şey:

__block NSMutableString *alertMessage; 
__block NSMutableString *otherString; 

void(^appendMessage)(NSMutableString*, NSString*)= ^(NSMutableString *string, NSString *append){ 

    if (!string) 
    { 
     string = [NSMutableString new]; 
    } 

    if ([append length] > 0) 
    { 
     [string appendString:@"\n"]; 
    } 

    [string appendString:append]; 
}; 

//The following do not work as intended 
appendMessage(alertMessage, @"Alert Part 1"); 
appendMessage(otherString, @"Bleh bleh");  

Ben ondan önce ilan değişkenlerini değiştirmek için yukarıdaki bloğu kullanmak isterler.

Böyle bir işlemi nasıl başarabilirim? Bu mümkün mü?

+0

Sadece bunu yapan bir C işlevi oluşturabilirsiniz. Neden bu amaçla bir blok kullanmak istersiniz? –

+0

@WolfgangSchreurs Blokta belirtilen işlem belirli bir fonksiyon içerisinde gereklidir. Bir C fonksiyonu aslında bir blok içinde aynı işlemi bildiren hile (veya bu konu için bir Objective-C) yaparsa da, kodun fonksiyon içinde kullanımının yanı sıra aynı şekilde daha okunabilir hale getirilmesinin ek yararı olacaktır. – ZeMoon

+0

neden bloğu önce (dışarıda) parametresini başlatamazsınız, bu 'soruna' neden olan tek şey budur – Wain

cevap

0

kodu, yazıldığı gibi, nesne oluşturma ile nesne üzerinde operasyonu şaşırtmak gibi görünüyor. Açıklık sağlamak amacıyla

, ya manipüle edilmesi kesilebilir bir nesne içerisinde geçer veya, değeri bloğu tarafından ayarlanacak tek __block değişkeni tanımlamak (ve burada bu değer anlamaya sonra mantık yapmak doldurulmalıdır).

Referans olarak bir öğeye geçmek, bir anti-desen olma özelliğiyle doğal olarak tehlikelidir (kodu asenkronize edilmek üzere yeniden kodlamayı denediğinizde ne olur? En azından __block durumunda, bloktan sonraki kod bakınız nil).

yani .:

__block NSMutableString *foo = [sourceString mutableCopy]; 
doIt(@"new stuff"); // appends to `foo` 
whereItShouldReallyGo = foo; 
+0

Elde etmek istediğim şey, nesnenin oluşturulmasını içeriyor. "Bir blok içinde dışarıda bildirilen bir nesne oluşturabilir miyim?" Buradaki tüm faaliyetlerin yardımıyla topladığım cevap NO'dur. Teşekkürler! – ZeMoon

1

Sorunuz büyüklüklerle üzerinde biraz kafa karışıklığı gösterir, belki şu yardımcı olacaktır. Amaç-Cı blok yöntemleri/fonksiyonları/bloklara tüm parametreleri değeri, örn geçirilir (Objective-) C

içinde

değiştirme parametreleri f(x) numaralı çağrıda, x değişkeninin değeri, değişkenin kendisine değil f geçirilir. Bu çağrı değeri olarak bilinir.

değişkenler olarak bilinen geçirilecek izin veriyoruz dil vardır çağrı bazında referans. Kullanılan argümanın bir değişken olması ve işlev içindeki parametre adı, sağlanan değişkenle etkili bir şekilde diğer adıyla'dır. Bu doğrudan (Objective-) C'de desteklenmez.

Ancak öykünme öykünümü (Objective-) C içinde yapabilirsiniz. Bir istisnai istisna ile yaygın olarak kullanılmaz: Birçok yöntem NSError * değerini döndürmek için kullanır.

daha sonra açıklama:

Ne elde etmek istediğim soru şimdi aşağı kaynar aslında ne nesne oluşturma içerir

. "Bir blok içinde dışarıda bildirilen bir nesne oluşturabilir miyim?" Buradaki tüm faaliyetlerin yardımıyla topladığım cevap NO'dur.

Yapmanız gereken tek şey, (yani tasarım hakkı mı?) Ve bunu yapmanın en iyi yolu.

belirli sorunu çözmek için basit yolu işlevi yazmaktır:

NSMutableString *alertMessage; 
NSMutableString *otherString; 

NSMutableString *(^appendMessage)(NSMutableString *, NSString *) = 
    ^(NSMutableString *string, NSString *append) 
    { 
     if (!string) 
     string = [NSMutableString new]; 

     if (append.length > 0) 
     { 
     [string appendString:@"\n"]; 
     [string appendString:append]; 
     } 

     return string; 
    }; 

alertMessage = appendMessage(alertMessage, @"Alert Part 1"); 
otherString = appendMessage(otherString, @"Bleh bleh"); 

gerçekten (gerçekten, gerçekten) yerine göre "değişken geçirmek" olabilir size istediğiniz Eğer adresini (& operatörünü kullanarak) ve indirgesini (* operatörünü kullanarak) bloğun içinden almak/ayarlamak için:

void (^appendMessage)(NSMutableString **, NSString *) = 
    ^(NSMutableString **stringPtr, NSString *append) 
    { 
     if (!stringPtr) return; // no "variable" passed 

     NSMutableString *string = *stringPtr; // use indirection to get the value in the passed variable 

     if (!string) 
     string = [NSMutableString new]; 

     if (append.length > 0) 
     { 
     [string appendString:@"\n"]; 
     [string appendString:append]; 
     } 

     *stringPtr = string; // use indirection to set the passed variable 
    }; 


appendMessage(&alertMessage, @"Alert Part 1"); // pass "variable" by passing its address 
appendMessage(&otherString, @"Bleh bleh"); 

Yukarıdaki kod geçerli olsa da, sizinki gibi basit durumlarda Objective-C'de genellikle kodlama uygulaması önerilmez.

Eğer ömür boyu o değişkenin endişeli gereken bir değişkenin adresini çekildikten sonra - değişken tahrip edildikten sonra size değişkene erişme adresi kullanmaya kalkarsanız programınız (başarısız olur sarkan işaretçi sorun) __block hakkında

ne?

Yukarıdaki örneklerin hiçbiri, __block her yerde kullanır.

Bir blok varsayılan olarak bir değişkene başvuruda bulunduğunda, blok oluşturulduğu anda değişkenlerini yakalar. __block özniteliği, değişkeni değişkeni (bu nedenle değeri, blok tarafından değiştirilebilir) yakalar ve gerekirse yakalama değişkeninin kullanım ömrünü değiştirir (böylece değişken en az yakalama bloğu kadar uzar. sarkan işaretçi sorunu). __block özniteliği farklı değişkenlerini temel almak istediğinizde durumunuzda geçerli değildir.

HTH