{"id":1286,"date":"2006-07-15T11:50:07","date_gmt":"2006-07-15T15:50:07","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=1286"},"modified":"2014-07-14T10:12:19","modified_gmt":"2014-07-14T14:12:19","slug":"cocoa-foreach-macro","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2006\/07\/15\/cocoa-foreach-macro\/","title":{"rendered":"Cocoa foreach Macro"},"content":{"rendered":"<p>\r\nI&rsquo;ve updated the macro that I use to iterate over Cocoa collections. As before, the idea is that you write <code>foreach( object, collection )<\/code>, where <code>object<\/code> is the name of the loop variable and <code>collection<\/code> is either an <code>NSEnumerator<\/code> or an object that responds to <code>-objectEnumerator<\/code>. <code>collection<\/code> is only evaluated once, and <code>IMP<\/code>-caching is used to speed up the calls to <code>-nextObject<\/code>.\r\n<\/p>\r\n\r\n<p>\r\nUnlike the <a href=\"http:\/\/mjtsai.com\/blog\/2003\/12\/08\/cocoa_enumeration\/\">old version<\/a>, all the variables are local to the loop; it does not pollute the outer scope. This requires that you set the &ldquo;C Language Dialect&rdquo; in Xcode to C99. Also, there is a new macro called <code>foreacht<\/code> that lets you specify a type for the loop variable. Then you can write <code>foreach( NSString *, string, collection )<\/code>, and if you write something like <code>[string count]<\/code> you&rsquo;ll get a compiler warning. Here&rsquo;s the code:\r\n<\/p>\r\n\r\n<pre>\r\n#define foreachGetEnumerator(c) \\\r\n    ([c respondsToSelector:@selector(objectEnumerator)] ? \\\r\n     [c objectEnumerator] : \\\r\n     c)\r\n#define foreachGetIMP(e) \\\r\n    [foreachEnum methodForSelector:@selector(nextObject)]\r\n#define foreachCallIMP(imp, e) \\\r\n    ((IMP)imp)(e, @selector(nextObject))\r\n#define foreachGetFirst(imp, e) \\\r\n    (e ? foreachCallIMP(imp, e) : nil)\r\n#define foreach(object, collection) \\\r\n    for ( id foreachCollection = collection, \\\r\n             foreachEnum = foreachGetEnumerator(foreachCollection), \\\r\n             foreachIMP = (id)foreachGetIMP(foreachEnum), \\\r\n             object = foreachGetFirst(foreachIMP, foreachEnum); \\\r\n          object; \\\r\n          object = foreachCallIMP(foreachIMP, foreachEnum) )\r\n#define foreacht(type, object, collection) \\\r\n    for ( type foreachCollection = (id)collection, \\\r\n               *foreachEnum = (id)foreachGetEnumerator((id)foreachCollection), \\\r\n               *foreachIMP = (id)foreachGetIMP((id)foreachEnum), \\\r\n               *object = foreachGetFirst(foreachIMP, foreachEnum); \\\r\n          object; \\\r\n          object = foreachCallIMP(foreachIMP, foreachEnum) )\r\n<\/pre>\r\n\r\n\r\n<p>\r\nUpdate: <a href=\"http:\/\/www.tidbits.com\/matt\/\">Matt Neuberg<\/a> (who prompted this post by sending me his modification of my original <code>foreach<\/code> to add the <code>type<\/code> parameter) didn&rsquo;t like the look of the casts and suggested using nested one-time <code>for<\/code> loops instead:\r\n<\/p>\r\n\r\n<pre>\r\n#define foreachGetEnumerator(c) \\\r\n    ([c respondsToSelector:@selector(objectEnumerator)] ? \\\r\n     [c objectEnumerator] : \\\r\n     c)\r\n#define foreacht(type, object, collection) \\\r\nfor ( id foreachCollection = collection; \\\r\n      foreachCollection; \\\r\n      foreachCollection = nil ) \\\r\n    for ( id foreachEnum = foreachGetEnumerator(foreachCollection); \\\r\n          foreachEnum; \\\r\n          foreachEnum = nil ) \\\r\n        for ( IMP foreachNext = [foreachEnum methodForSelector:@selector(nextObject)]; \\\r\n              foreachNext; \\\r\n              foreachNext = NULL ) \\\r\n            for ( type object = foreachNext(foreachEnum, @selector(nextObject)); \\\r\n                  object; \\\r\n                  object = foreachNext(foreachEnum, @selector(nextObject)) )\r\n<\/pre>\r\n\r\n<p>\r\nAnd with that <code>foreacht<\/code>, you can now define <code>foreach<\/code> like so:\r\n<\/p>\r\n\r\n<pre>\r\n#define foreach(object, collection) foreacht(id, object, (collection))\r\n<\/pre>\r\n","protected":false},"excerpt":{"rendered":"<p>I&rsquo;ve updated the macro that I use to iterate over Cocoa collections. As before, the idea is that you write foreach( object, collection ), where object is the name of the loop variable and collection is either an NSEnumerator or an object that responds to -objectEnumerator. collection is only evaluated once, and IMP-caching is used [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[69,941,54,71],"class_list":["post-1286","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-cocoa","tag-macros","tag-objective-c","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1286","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=1286"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1286\/revisions"}],"predecessor-version":[{"id":9138,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1286\/revisions\/9138"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=1286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=1286"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=1286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}