{"id":1470,"date":"2008-12-17T20:12:41","date_gmt":"2008-12-17T23:12:41","guid":{"rendered":"http:\/\/brockerhoff.net\/bb\/viewtopic.php?p=2621"},"modified":"2010-05-08T12:15:23","modified_gmt":"2010-05-08T15:15:23","slug":"cocoa-musings-pt-2","status":"publish","type":"post","link":"https:\/\/brockerhoff.net\/blog\/2008\/12\/17\/cocoa-musings-pt-2\/","title":{"rendered":"Cocoa musings pt.2"},"content":{"rendered":"<p>One of the nice things Objective-C inherited from C is the switch statement. If you have set different tags in all your menu items, you often find you can do things like:<\/p>\n<pre><code>- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {\r\n\u00a0 \u00a0switch ([menuItem action]) {\r\n\u00a0 \u00a0case 1:\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0case 2:\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0}\r\n\u00a0 \u00a0return YES;\r\n}<\/code><\/pre>\n<p>Those tags have to be set in Interface Builder, and you probably will have an enum somewhere to use symbolic constants instead. However, the standard C switch() is restricted to integer values; you can&#8217;t switch on strings or selectors. So, if you don&#8217;t want tags and need to switch on the menu item&#8217;s selectors, you&#8217;ll have to do:<\/p>\n<pre><code>\r\n- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {\r\n\u00a0 \u00a0SEL action = [menuItem action];\r\n\u00a0 \u00a0if (action==@selector(firstAction:)) {\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0} else if (action==@selector(secondAction:)) {\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0} else...\r\n\u00a0 \u00a0return YES;\r\n}<\/code><\/pre>\n<p>Bearable if you have two, or even four or five cases, but what if there are dozens? Or suppose you have to compare strings instead of selectors:<\/p>\n<pre><code>- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {\r\n\u00a0 \u00a0NSString* title = [menuItem title];\r\n\u00a0 \u00a0if ([title isEqualToString:@\"firstTitle\"]) {\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0} else if ([title isEqualToString:@\"secondTitle\"]) {\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0} else...\r\n\u00a0 \u00a0return YES;\r\n}<\/code><\/pre>\n<p>Not that it&#8217;s recommendable, in practice, to compare menu item titles, but it&#8217;s a good example.<br \/>\nWell, there are other ways to make this more readable, or even more efficient. But here&#8217;s one neat way to convert a group of strings into integers for use in a switch(). First, let&#8217;s write an utility C function to do so:<\/p>\n<pre><code>NSUInteger CaseCodeForString(NSString* string) {\r\n\u00a0 \u00a0static NSArray* array = nil;\r\n\u00a0 \u00a0if (!array) {\r\n\u00a0 \u00a0\u00a0 \u00a0array = [[NSArray alloc] initWithObjects:\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0@\"zeroth string\",\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0@\"first string\",\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0@\"second string\",\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0@\"third string\",\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0\u00a0 \u00a0nil];\r\n\u00a0 \u00a0}\r\n\u00a0 \u00a0return [array indexOfObject:string];\r\n}<\/code><\/pre>\n<p>Note the standard lazy allocate-once trick of declaring array static, initialize it to nil, and test before using. Anyway, this function will return 0 if you feed it @&#8221;zeroth string&#8221;, 1 for @&#8221;first string&#8221; and so forth&#8230; and return NSNotFound if the string isn&#8217;t in the array. So you could, in our last example, do:<\/p>\n<pre><code>- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {\r\n\u00a0 \u00a0switch (CaseCodeForString([menuItem title])) {\r\n\u00a0 \u00a0case 0:\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0case 1:\r\n\u00a0 \u00a0\u00a0 \u00a0...\r\n\u00a0 \u00a0}\r\n\u00a0 \u00a0return YES;\r\n}<\/code><\/pre>\n<p>If there are many strings, this will be faster than a series of isEqualToString: calls; this is because NSArray uses a hash table to find the index of a particular object, and only goes into the actual string comparison if the two string&#8217;s -hash methods return the same value.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the nice things Objective-C inherited from C is the switch statement. If you have set different tags in all your menu items, you often find you can do things like: &#8211; (BOOL)validateMenuItem:(NSMenuItem*)menuItem { \u00a0 \u00a0switch ([menuItem action]) { \u00a0 \u00a0case 1: \u00a0 \u00a0\u00a0 \u00a0&#8230; \u00a0 \u00a0case 2: \u00a0 \u00a0\u00a0 \u00a0&#8230; \u00a0 \u00a0} \u00a0 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[26],"class_list":["post-1470","post","type-post","status-publish","format-standard","hentry","category-dev","tag-cocoa"],"featured_image_src":null,"author_info":{"display_name":"Rainer Brockerhoff","author_link":"https:\/\/brockerhoff.net\/blog\/author\/rbrockerhoff\/"},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1q3Zc-nI","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts\/1470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/comments?post=1470"}],"version-history":[{"count":0,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts\/1470\/revisions"}],"wp:attachment":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/media?parent=1470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/categories?post=1470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/tags?post=1470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}