Soru NSString'de Object-C geçişi yapılabilir mi?


Bunu yeniden yazmanın daha zekice bir yolu var mı?

if ([cardName isEqualToString:@"Six"]) {
    [self setValue:6];
} else if ([cardName isEqualToString:@"Seven"]) {
    [self setValue:7];
} else if ([cardName isEqualToString:@"Eight"]) {
    [self setValue:8];
} else if ([cardName isEqualToString:@"Nine"]) {
    [self setValue:9];
} 

151
2017-11-17 03:26


Menşei


Hayır, sadece int / bool / char / etc türlerinde çalışır. - chown
Bu soru bir saat önce yayınlanmış olana benzer. stackoverflow.com/questions/8161319/... ) - Michael Dautermann
Bunu yapmanın birkaç alternatif yolu var. Örneğin, değerlerle bir dizi yükleyin ve dizide bir eşleşme arayın. Çok verimli değil, ancak kod çoğaltmayı azaltırlar. - Hot Licks
Bir yan not olarak, Apple'ın yeni dili (Swift) şimdi bir anahtar deyiminde dizeleri karşılaştırmaya izin veriyor! - jaredsmith
Swift'e geçin;) - tothemario


Cevaplar:


Maalesef yapamazlar. Bu, anahtar ifadelerinin en iyi ve en çok aranan kullanımlarından biridir, bu yüzden umarız şimdi (şimdi) Java (ve diğerleri) bekçisine atlarlar!

Kart isimleri yapıyorsanız, belki de her bir kart nesnesine bir tamsayı değeri atayın ve bunu açın. Ya da belki bir sayı olarak kabul edilen ve bu nedenle devreye alınabilen bir enum.

Örneğin.

typedef enum{
  Ace, Two, Three, Four, Five ... Jack, Queen, King

} CardType;

Bu şekilde yapıldığında, Ace, vaka 1'e eşit olacak, 1'inci duruma göre iki, vb.


137
2017-11-17 03:30



whaaaaaaaat ?? vay .. sadece vay .. - abbood
Yapılması gereken tek yol budur. - Tristan
@abbood Enum hakkında daha fazla bilgi için, bkz. NS_ENUM ve NS_OPTIONS Mattt Thompson tarafından. - Basil Bourque
@abbood Yorumunuz ne anlama geliyor? Bunun gibi görünüyor, kötü bir cevap ama bana iyi görünüyor. Açıklar mısınız? - Alan Andrade
Anladığım kadarıyla, CardType kapalı olanlara eşit olamaz @"" Örneğin: [CardType isEqualToString:@"Three"] - Adromil Balais


Bu gibi bir blok sözlüğü oluşturabilirsiniz:

NSString *lookup = @"Hearts"; // The value you want to switch on

typedef void (^CaseBlock)();

// Squint and this looks like a proper switch!
NSDictionary *d = @{
    @"Diamonds": 
    ^{ 
        NSLog(@"Riches!"); 
    },
    @"Hearts":
    ^{ 
        self.hearts++;
        NSLog(@"Hearts!"); 
    },
    @"Clubs":
    ^{ 
        NSLog(@"Late night coding > late night dancing"); 
    },
    @"Spades":
    ^{ 
        NSLog(@"I'm digging it"); 
    }
};

((CaseBlock)d[lookup])(); // invoke the correct block of code

'Varsayılan' bölümüne sahip olmak için son satırı şununla değiştirin:

CaseBlock c = d[lookup];
if (c) c(); else { NSLog(@"Joker"); }

Umarım Apple birkaç yeni numarayı 'değiştirir'.


113
2018-04-16 16:26



Bunun gerçekten kötü ya da gerçekten havalı olup olmadığını söyleyemem. Bunu yapmayı hiç düşünmemiştim, teşekkürler. - endy
Böyle garip şeyler yaparken, neden blok nesneler için bir NSDictionary NSString anahtarlarıyla dolu olan ve sonra varsayılan durumlar için başka bir blok sağlayan kendi sınıfınızı yaratmıyorsunuz? Abonelik gösterimini bile destekleyebilirsin. - ArtOfWarfare
@endy Gerçekten çok iyi oy kullanıyorum. - Tom Howard
Sadece bunun için bir NSDictionary alt sınıfı yaparsanız ekstra puan: P - CommaToast
Kapağın altında, C # bu büyük anahtar ifadeleri için yapar. - Hank Schultz


Benim için, kolay bir yol:

NSString *theString = @"item3";   // The one we want to switch on
NSArray *items = @[@"item1", @"item2", @"item3"];
int item = [items indexOfObject:theString];
switch (item) {
    case 0:
       // Item 1
       break;
    case 1:
       // Item 2
       break;
    case 2:
       // Item 3
       break;
    default:
       break;
}

68
2017-09-10 01:46



Bunu severim. Bu sorunun cevabını arayanların çoğunun gereksinimlerini karşılar, javascript'te benzer bir anahtarın yazmasından çok daha fazla yazmaz ve insan tarafından okunabilir. - e.w. parris
Bu kesmek JS anahtarı ile karşılaştırmak olmaz. Sonraki programlayıcı item1 ile item2 arasında bir öğe eklerse ne olur? Hataların tanıtımı için çok fazla potansiyel - Aras
onun güzel bir hack olsa, bu yüzden size çaba için başparmak vermek :) - Aras
@Aras Bir sonraki programcının yeni bir giriş eklemesi gerekiyorsa, bunu işlemek için sonunda sonunda yeni bir durum ifadesiyle dizinin sonuna eklerler. Yani @ "item0" dizideki @ "item3" ifadesinden sonra eklenebilir, ardından bir vaka 3 ekleyiniz: işlemek için. - sbonkosky
Ben tamamen senin tarzını seviyorum. Çok temiz. Ben kategori yazıyorum ve benimle dize iken UIColor dönmek zorunda. - Alix


Maalesef, anahtar ifadeleri yalnızca ilkel türlerde kullanılabilir. Yine de koleksiyonları kullanarak birkaç seçeneğiniz var.

Muhtemelen en iyi seçenek, her değeri bir NSDictionary uygulamasında bir giriş olarak saklamak olabilir.

NSDictionary *stringToNumber = [NSDictionary dictionaryWithObjectsAndKeys:
                                              [NSNumber numberWithInt:6],@"Six",
                                              [NSNumber numberWithInt:7],@"Seven",
                                              [NSNumber numberWithInt:8],@"Eight",
                                              [NSNumber numberWithInt:9],@"Nine",
                                              nil];
NSNumber *number = [stringToNumber objectForKey:cardName];
if(number) [self setValue:[number intValue]];

9
2017-11-17 03:34





İşte bunu yazmanın daha zekice yolu. Kullanmak NSNumberFormatter içinde "yazım stili":

NSString *cardName = ...;

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterSpellOutStyle];
NSNumber *n = [nf numberFromString:[cardName lowercaseString]];
[self setValue:[n intValue]];
[nf release];

Sayı biçimlendiricisinin dizenin küçültülmesini istediğini unutmayın, bu yüzden bunu biçimlendiriciye iletmeden önce kendimiz yapmalıyız.


6
2017-11-17 04:10





Bunu yapmanın başka yolları var ama switch onlardan biri değil.

Örneğinizde olduğu gibi sadece birkaç dizeniz varsa, sahip olduğunuz kod gayet iyi. Çok sayıda vakanız varsa, dizeleri bir sözlükte anahtar olarak saklayabilir ve karşılık gelen değeri arayabilirsin:

NSDictionary *cases = @{@"Six" : @6,
                        @"Seven" : @7,
                        //...
                       };

NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
    [self setValue:[value intValue]];
}

6
2017-11-17 03:31





Biraz geç ama gelecekte herkes için bunu benim için işe alabiliyordum.

#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT

4
2017-09-14 20:00



Bu ilginç. Daha fazla detay verebilir misin? - Chen Li Yong


Objective-c bu açıdan c'den farklı değildir, yalnızca c'nin (ve preproc def'in NSInteger, NSUInteger gibi olmasından ötürü, sadece nihai tipte bir tip yazılmıştır) açılabilir.

Wikipedia:

c sözdizimi:

Anahtar deyimi, bir ifadenin değerine bağlı olarak denetimin çeşitli ifadelerden birine aktarılmasına neden olur. İntegral tip olmalı.

İntegral Tipleri:

Bilgisayar bilimlerinde bir tamsayı, integral veri tipinin bir verisidir.   Matematiksel bazı sonlu alt kümesini temsil eden veri türü   tamsayılar. Entegre veri tipleri farklı boyutlarda olabilir ve olabilir veya olabilir   negatif değerler içermesine izin verilmez.


3
2017-11-17 03:35





BUGÜNE KADAR.. benim FAVORITE "ObjC Eklenti" dir ObjectMatcher

objswitch(someObject)
    objcase(@"one") { // Nesting works.
        objswitch(@"b")
            objcase(@"a") printf("one/a");
            objcase(@"b") printf("one/b");
            endswitch // Any code can go here, including break/continue/return.
    }
    objcase(@"two") printf("It's TWO.");  // Can omit braces.
    objcase(@"three",     // Can have multiple values in one case.
        nil,              // nil can be a "case" value.
        [self self],      // "Case" values don't have to be constants.
        @"tres", @"trois") { printf("It's a THREE."); }
    defaultcase printf("None of the above."); // Optional default must be at end.
endswitch

VE non-stringlerle çalışır, TOO ... döngüler halinde bile!

for (id ifNumericWhatIsIt in @[@99, @0, @"shnitzel"])
    objswitch(ifNumericWhatIsIt)
        objkind(NSNumber)  printf("It's a NUMBER.... "); 
        objswitch([ifNumericWhatIsIt stringValue])
            objcase(@"3")   printf("It's THREE.\n"); 
            objcase(@"99")  printf("It's NINETY-NINE.\n"); 
            defaultcase     printf("some other Number.\n");
       endswitch
    defaultcase printf("It's something else entirely.\n");
endswitch

It's a NUMBER.... It's NINETY-NINE.
It's a NUMBER.... some other Number.
It's something else entirely.

En iyisi, çok az var {...}Var, :ve ()'ler


3
2017-10-25 15:56





Partiye geç kaldım ama soruyu belirtildiği şekilde cevapladaha akıllı bir yol var:

NSInteger index = [@[@"Six", @"Seven", @"Eight", @"Nine"] indexOfObject:cardName];
if (index != NSNotFound) [self setValue: index + 6];

Bunu not et indexOfObject kullanarak maçı arayacak isEqual:aynen sorudaki gibi.


1
2017-12-05 10:08





Cris'ın cevapta @Cris cevabı üzerine yorum yapamam ama şunu söylemek isterim:

@ Cris'ın yöntemi için bir LIMITATION var:

typedef enum alfanümerik değerleri almaz

typedef enum
{
  12Ace, 23Two, 23Three, 23Four, F22ive ... Jack, Queen, King

} CardType;

Yani burada başka bir tane var:

Akış üzerinden bağlantı yığınıBu kullanıcı yanıtına git "user1717750"


0
2017-09-19 13:18