Objective-C có thể bật NSString không?


166

Có cách nào thông minh hơn để viết lại điều này?

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];
} 

1
Không, switch chỉ hoạt động trên các loại int / bool / char / etc.
chown

câu hỏi này có phần giống với câu hỏi này chỉ được đăng cách đây một giờ ( stackoverflow.com/questions/8161319/
mẹo

3
Có một số cách khác để làm điều đó. Ví dụ, tải một mảng với các giá trị và tìm kiếm sự trùng khớp trong mảng. Không có hiệu quả khủng khiếp, nhưng chúng làm giảm sự sao chép mã.
Hot Licks

4
Là một lưu ý phụ, ngôn ngữ mới của Apple (Swift) hiện cho phép so sánh các chuỗi trong câu lệnh chuyển đổi!
jaredsmith

4
Chuyển sang Swift;)
tothemario 30/03/2016

Câu trả lời:


147

Thật không may, họ không thể. Đây là một trong những cách sử dụng tốt nhất và được tìm kiếm nhiều nhất sau khi sử dụng các câu lệnh chuyển đổi, vì vậy hy vọng họ hy vọng vào bandwagon (bây giờ) (và những người khác)!

Nếu bạn đang thực hiện tên thẻ, có thể gán cho mỗi đối tượng thẻ một giá trị nguyên và bật nó. Hoặc có lẽ là một enum, được coi là một số và do đó có thể được bật.

ví dụ

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

} CardType;

Thực hiện theo cách này, Ace sẽ bằng với trường hợp 0, Hai là trường hợp 1, v.v.


4
@abbood Để biết thêm thông tin về enum, hãy xem bài đăng NS_ENUM & NS_OPTIONS của Mattt Thompson.
Basil Bourque

@abbood Nhận xét của bạn có nghĩa là gì? Âm thanh như thế này là một câu trả lời xấu nhưng có vẻ Ok với tôi. Bạn có thể giải thích ?
Alan Andrade

Theo tôi hiểu, CardTypekhông thể bằng bất kỳ bao vây nào, @""ví dụ:[CardType isEqualToString:@"Three"]
Adromil Balais 18/07/17

119

Bạn có thể thiết lập một từ điển các khối, như thế này:

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

Để có phần 'mặc định', hãy thay thế dòng cuối cùng bằng:

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

Hy vọng Apple sẽ dạy 'chuyển đổi' một vài thủ thuật mới.


34
Tôi không thể biết nếu điều này thực sự khó chịu hoặc thực sự mát mẻ. Sẽ không bao giờ nghĩ làm điều này, cảm ơn.
endy

2
Trong khi chúng ta đang làm những thứ kỳ lạ như thế này, tại sao không tạo lớp riêng của bạn bao bọc một khóa NSString đầy đủ các khóa NSString cho các đối tượng khối và sau đó cung cấp một khối khác cho các trường hợp mặc định? Bạn thậm chí có thể có nó hỗ trợ ký hiệu đăng ký.
ArtOfWarfare

1
Điểm bổ sung nếu bạn tạo một lớp con
NSDipedia

2
Dưới mui xe, đây là cách C # thực hiện cho các câu lệnh chuyển đổi lớn.
Hank Schultz

77

Đối với tôi, một cách dễ dàng tốt đẹp:

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;
}

1
Tôi thích điều này. Nó trả lời các nhu cầu của hầu hết những người đang tìm kiếm một câu trả lời cho vấn đề này, nó không cần gõ nhiều hơn so với một công tắc tương tự sẽ có trong javascript và nó có thể đọc được.
ew parris

4
Tôi sẽ không so sánh bản hack này với bộ chuyển đổi JS. Điều gì xảy ra nếu lập trình viên tiếp theo thêm một mục giữa item1 và item2? Quá nhiều tiềm năng để giới thiệu các lỗi
Aras

Mặc dù vậy, đây là một bản hack hay, vì vậy tôi cho bạn nỗ lực :)
Aras

@Aras Nếu lập trình viên tiếp theo cần thêm một mục mới thì họ sẽ thêm nó vào cuối mảng với một câu lệnh tình huống mới ở cuối để xử lý nó. Vì vậy, @ "item0" có thể được thêm vào sau @ "item3" trong mảng, sau đó thêm trường hợp 3: để xử lý nó.
sbonkosky

1
Tôi hoàn toàn thích cách của bạn. Nó rất gọn gàng. Tôi đang viết thể loại và cần trả lại UIColor trong khi tôi có chuỗi với tôi.
Alix

11

Thật không may, các câu lệnh chuyển đổi chỉ có thể được sử dụng trên các kiểu nguyên thủy. Bạn có một vài lựa chọn sử dụng bộ sưu tập, mặc dù.

Có lẽ tùy chọn tốt nhất sẽ là lưu trữ từng giá trị dưới dạng một mục trong NSDipedia.

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]];

8

Hơi muộn một chút nhưng với bất kỳ ai trong tương lai tôi đã có thể làm việc này cho tôi

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

Hay đấy. Bạn có thể giải thích nhiều hơn?
Chen Li Yong

6

Đây là cách thông minh hơn để viết điều đó. Đó là sử dụng một NSNumberFormattertrong các "phong cách đánh vần-out" :

NSString *cardName = ...;

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

Lưu ý rằng trình định dạng số muốn chuỗi được hạ thấp, vì vậy chúng ta phải tự làm điều đó trước khi chuyển nó vào trình định dạng.


5

Có nhiều cách khác để làm điều đó, nhưng switchkhông phải là một trong số đó.

Nếu bạn chỉ có một vài chuỗi, như trong ví dụ của bạn, mã bạn có là ổn. Nếu bạn có nhiều trường hợp, bạn có thể lưu trữ các chuỗi dưới dạng các khóa trong từ điển và tra cứu giá trị tương ứng:

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

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

4

B FNG FAR .. Tiện ích bổ sung "ObjC" của tôi là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

VÀ nó hoạt động với các chuỗi không, QUÁ ... trong các vòng lặp, thậm chí!

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.

Trên hết, có một vài SO {...}, :'s và ()'


3

Objective-c không khác với c ở khía cạnh này, nó chỉ có thể chuyển đổi những gì c có thể (và các defproc như NSInteger, NSUInteger, vì cuối cùng chúng chỉ là một loại không thể tách rời).

Wikipedia:

cú pháp c :

Câu lệnh chuyển đổi làm cho điều khiển được chuyển đến một trong một số câu lệnh tùy thuộc vào giá trị của biểu thức, phải có kiểu tích phân .

Các loại tích phân :

Trong khoa học máy tính, một số nguyên là một mốc dữ liệu của kiểu dữ liệu tích phân, một kiểu dữ liệu đại diện cho một số tập hợp con hữu hạn của các số nguyên toán học. Các loại dữ liệu tích hợp có thể có kích thước khác nhau và có thể hoặc không được phép chứa các giá trị âm.


2

Tôi đến bữa tiệc muộn, nhưng để trả lời câu hỏi như đã nêu , có một cách thông minh hơn:

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

Lưu ý rằng indexOfObjectsẽ tìm kiếm trận đấu bằng cách sử dụng isEqual:, chính xác như trong câu hỏi.


2

Xây dựng trên ý tưởng @Graham Perks được đăng trước đó, đã thiết kế một lớp đơn giản để thực hiện chuyển đổi trên chuỗi khá đơn giản và sạch sẽ.

@interface Switcher : NSObject

+ (void)switchOnString:(NSString *)tString
                 using:(NSDictionary<NSString *, CaseBlock> *)tCases
           withDefault:(CaseBlock)tDefaultBlock;

@end

@implementation Switcher

+ (void)switchOnString:(NSString *)tString
                 using:(NSDictionary<NSString *, CaseBlock> *)tCases
           withDefault:(CaseBlock)tDefaultBlock
{
    CaseBlock blockToExecute = tCases[tString];
    if (blockToExecute) {
        blockToExecute();
    } else {
        tDefaultBlock();
    }
}

@end

Bạn sẽ sử dụng nó như thế này:

[Switcher switchOnString:someString
                   using:@{
                               @"Spades":
                               ^{
                                   NSLog(@"Spades block");
                               },
                               @"Hearts":
                               ^{
                                   NSLog(@"Hearts block");
                               },
                               @"Clubs":
                               ^{
                                   NSLog(@"Clubs block");
                               },
                               @"Diamonds":
                               ^{
                                   NSLog(@"Diamonds block");
                               }
                           } withDefault:
                               ^{
                                   NSLog(@"Default block");
                               }
 ];

Khối chính xác sẽ thực hiện theo chuỗi.

Ý chính cho giải pháp này


0

Tôi không thể nhận xét về câu trả lời của cris trên câu trả lời @Cris nhưng tôi muốn nói rằng:

Có một GIỚI HẠN cho phương pháp của @ cris:

typedef enum sẽ không lấy các giá trị chữ và số

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

} CardType;

Vì vậy, đây là một cái khác:

Liên kết Stack overflow Chuyển đến câu trả lời của người dùng này "user1717750"


-1
typedef enum
{
    Six,
    Seven,
    Eight
} cardName;

- (void) switchcardName:(NSString *) param {
    switch([[cases objectForKey:param] intValue]) {
        case Six:
            NSLog(@"Six");
            break;
        case Seven:
            NSLog(@"Seven");
            break;
        case Eight:
            NSLog(@"Eight");
            break;
        default: 
            NSLog(@"Default");
            break;
    }
}

Thưởng thức mã hóa .....

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.