{"id":9132,"date":"2014-07-13T21:47:57","date_gmt":"2014-07-14T01:47:57","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=9132"},"modified":"2014-07-14T10:12:31","modified_gmt":"2014-07-14T14:12:31","slug":"swift-and-cocoa-error-handling","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2014\/07\/13\/swift-and-cocoa-error-handling\/","title":{"rendered":"Swift and Cocoa Error Handling"},"content":{"rendered":"<p>I&rsquo;ve not see much written about how to do real-world Cocoa error handling in Swift. That is, you&rsquo;re calling Objective-C methods with <code>NSError **<\/code> parameters and need to return an <code>NSError<\/code> back to your caller. This is very common with Cocoa.<\/p>\n<p><code>NSError<\/code> is <a href=\"https:\/\/github.com\/rentzsch\/JRErr\">unwieldy<\/a>, especially when you must consider that the output parameter could be <code>NULL<\/code>. The way I handle this in Objective-C is to use a macro to reduce the amount of error handling code that&rsquo;s visible:<\/p>\n<pre>\nNSError *e = nil;\nNSString *string = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&amp;e];\nMJT_REQUIRE(string, e, error);\n[string doSomething];\n<\/pre>\n<p>This leaves straight-line code, with no indentation, for the normal case. The macro, inspired by Apple&rsquo;s <a href=\"https:\/\/opensource.apple.com\/source\/CarbonHeaders\/CarbonHeaders-18.1\/AssertMacros.h\">AssertMacros.h<\/a>, does nothing if its first parameter indicates success. Otherwise, it propagates the second parameter (the local error object) to the third parameter (the passed-in error pointer), but only if the latter isn&rsquo;t <code>NULL<\/code>. It can also add some contextual information to error object, to track the source of the error. Lastly, it returns <code>nil<\/code> to indicate failure to the caller.<\/p>\n<p>(I also have <code>MJT_BOOL_REQUIRE()<\/code>, which returns <code>NO<\/code> instead of <code>nil<\/code>, and <code>MJT_REQUIRE_PARAMETER(param, error)<\/code>, for when a parameter can&rsquo;t be <code>nil<\/code>. This is sometimes preferable to raising an exception with <code>NSParameterAssert()<\/code>, and it is otherwise very verbose to construct an appropriate <code>NSError<\/code> to return.)<\/p>\n<p>Swift doesn&rsquo;t have macros, so it&rsquo;s not clear to me how this sort of pattern can be encapsulated. It <a href=\"https:\/\/developer.apple.com\/library\/prerelease\/ios\/documentation\/Swift\/Conceptual\/BuildingCocoaApps\/AdoptingCocoaDesignPatterns.html\">looks like<\/a> the code would be something like this:<\/p>\n<pre>\nvar e : NSError?\nlet possibleString = NSString(contentsOfURL:url, encoding:NSUTF8StringEncoding, error:&amp;e)\nif possibleString == nil {\n    if error {\n        error.memory = addErrorContext(e, context)\n    }\n    return nil\n}\nlet string = possibleString as NSString\nstring.doSomething()\n<\/pre>\n<p>I don&rsquo;t like the way this code looks. I could probably write a helper function to make it something like:<\/p>\n<pre>\nvar e : NSError?\nlet possibleString = NSString(contentsOfURL:url, encoding:NSUTF8StringEncoding, error:&amp;e)\nif failed(possibleString, e, error) {\n    return nil\n}\nlet string = possibleString as NSString\nstring.doSomething()\n<\/pre>\n<p>But I don&rsquo;t see how to hide that <code>if<\/code> and <code>return<\/code>. And then there is the matter of having to create a second variable for the non-optional string if you don&rsquo;t want to add <code>!<\/code> after each use. I hope I&rsquo;m missing something here, because it looks like Swift is making basic code more tedious without providing any real benefit.<\/p>","protected":false},"excerpt":{"rendered":"<p>I&rsquo;ve not see much written about how to do real-world Cocoa error handling in Swift. That is, you&rsquo;re calling Objective-C methods with NSError ** parameters and need to return an NSError back to your caller. This is very common with Cocoa. NSError is unwieldy, especially when you must consider that the output parameter could be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","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,857,54,71,901],"class_list":["post-9132","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-cocoa","tag-macros","tag-nserror","tag-objective-c","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/9132","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=9132"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/9132\/revisions"}],"predecessor-version":[{"id":9139,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/9132\/revisions\/9139"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=9132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=9132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=9132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}