{"id":2222,"date":"2015-04-18T07:49:36","date_gmt":"2015-04-18T14:49:36","guid":{"rendered":"http:\/\/www.wellgolly.com\/?p=2222"},"modified":"2015-04-20T14:59:07","modified_gmt":"2015-04-20T21:59:07","slug":"ns_designated_initializer-warnings","status":"publish","type":"post","link":"https:\/\/www.wellgolly.com\/?p=2222","title":{"rendered":"NS_DESIGNATED_INITIALIZER warnings"},"content":{"rendered":"<p>I programmatically create several tables and the code has worked fine for years. It did not generate any warnings two weeks ago when I last ran it. I\u2019ve since updated to Xcode 8.3 and 10.10.3 and now get three warnings for each UITableViewController.<\/p>\n<p><pre><code class=\"\u2019smallest\u2019 preserve-code-formatting\">\nMethod override for the designated initializer of the superclass &#039;-initWithStyle:&#039; not found.\nMethod override for the designated initializer of the superclass &#039;-initWithCoder:&#039; not found.\nMethod override for the designated initializer of the superclass &#039;-initWithNibName:bundle:&#039; not found.\n<\/code><\/pre><br \/>\nThe code to initialize the table is similar for all of my tables:<\/p>\n<p><pre><code class=\"\u2019smallest\u2019 preserve-code-formatting\">\n- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; withScoreKeeper:(ScoreKeeper *)scorer \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;withWordList:(WordList *)wordlist {\n\n&nbsp;&nbsp;&nbsp;&nbsp;self = [super initWithStyle:UITableViewStyleGrouped];\n\n&nbsp;&nbsp;&nbsp;&nbsp;if (self) {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_mObjContext = context;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_scoreKeeper = scorer;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_wordList = wordlist;\n&nbsp;&nbsp;&nbsp;&nbsp;}\n&nbsp;&nbsp;&nbsp;&nbsp;return self;\n}\n<\/code><\/pre><br \/>\nand the .h looks like this:<\/p>\n<p><pre><code class=\"\u2019smallest\u2019 preserve-code-formatting\">\n@interface SettingsTableViewController : UITableViewController {\n&nbsp;&nbsp;&nbsp;&nbsp;UIPopoverController *popover;\n\n}\n&nbsp;&nbsp;&nbsp;&nbsp;- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; withScoreKeeper:(ScoreKeeper *)scorer \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;withWordList:(WordList *)wordlist NS_DESIGNATED_INITIALIZER;\n<\/code><\/pre><\/p>\n<p>Here\u2019s what I found out. I am not a programmer, so parts could be mistaken.<\/p>\n<p>When I opened my project for the first time with Xcode 5 and Xcode 6, I was prompted to &#8220;Convert to Modern Objective-C Syntax&#8221;. (The latest version of Xcode puts it under Edit > Convert > Convert to Modern Objective-C Syntax.) I allowed Xcode to convert everything and understood most of the changes. I understood how NS_DESIGNATED_INITIALIZER works but not why it works. Since I had no compiler errors and everything worked as before, I promptly forgot about it. In the latest version of Xcode, they appear to have updated the compiler and that\u2019s what triggered my warning message.<\/p>\n<p>From Apple\u2019s notes: <a href=\"https:\/\/developer.apple.com\/library\/ios\/releasenotes\/ObjectiveC\/ModernizationObjC\/AdoptingModernObjective-C\/AdoptingModernObjective-C.html\">Adopting Modern Objective C<\/a><\/p>\n<div class='indent'>\nUsing this macro introduces a few restrictions:<\/p>\n<p>The implementation of a designated initializer must chain to a superclass init method (with [super init&#8230;]) that is a designated initializer for the superclass.<\/p>\n<p>The implementation of a convenience initializer (an initializer not marked as a designated initializer within a class that has at least one initializer marked as a designated initializer) must delegate to another initializer (with [self init&#8230;]).<\/p>\n<p>If a class provides one or more designated initializers, it must implement all of the designated initializers of its superclass.\n<\/p><\/div>\n<p>Here\u2019s what I think happened. First, I got three warning messages because UITableViewController has three designated initializers.<br \/>\n<pre><code class=\"\u2019smallest\u2019 preserve-code-formatting\">\n- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER;\n- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER;\n- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;\n<\/code><\/pre><br \/>\nI violated the third restriction because I did not implement all of the designated initializers of the superclass.<\/p>\n<p>Removing the NS_DESIGNATED_INITIALIZER macro from the .h files made the warnings go away. <\/p>\n<p>The question then arises, Do I care that these classes have no designated initializers? Probably not.<br \/>\nFirst, there are no other initializers in these classes, so I won\u2019t accidentally call the wrong one. Second, I\u2019m not a programmer by training, so when I started writing apps, I used the procedural programming style that I was used to. Until recently, I had never subclassed a class. So I won\u2019t be subclassing this one and there won\u2019t be any subclasses to worry about. Now that I know a bit more about Objective C, it turns out that every class I wrote was a subclass of one of iOS\u2019s classes and that actually explains a bit about why I was getting the errors.<\/p>\n<p>I did not realize that I could create the table view object by calling a method on its superclass. For example, this call works:<br \/>\n<pre><code class=\"preserve-code-formatting\">\nSettingsTableViewController *stvc = [[SettingsTableViewController alloc] initWithStyle: UITableViewStyleGrouped];\n<\/code><\/pre><br \/>\nIt works even when I have NS_DESIGNATED_INITIALIZER set. Presumably no other warnings are sent because the compiler is already complaining about not calling a designated initializer of super.<\/p>\n<p>And as long as the views called in the table view do not need any of the objects that were passed in, everything is fine. If a view that is linked to in the table does need one of the objects, then obviously the app crashes. <\/p>\n<p>Since I never want to call anything but the designated initializer, it was suggested that I use  NSAssert() to make sure that I don\u2019t call the designated initializers of my superclass, and make all the warnings go away with this code:<br \/>\n<pre><code class=\"preserve-code-formatting\">\n- (instancetype)initWithStyle:(UITableViewStyle)style {\n&nbsp;&nbsp;&nbsp;&nbsp;NSAssert(NO, @&quot;%@&quot;, @&quot;Tried to implement with initWithStyle&quot;);\n&nbsp;&nbsp;&nbsp;&nbsp;self = [self initInManagedObjectContext:nil withScoreKeeper:nil withWordList:nil];\n&nbsp;&nbsp;&nbsp;&nbsp;return self;\n}\n\n- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {\n&nbsp;&nbsp;&nbsp;&nbsp;NSAssert(NO, @&quot;%@&quot;, @&quot;Tried to implement with initWithNibName&quot;);\n&nbsp;&nbsp;&nbsp;&nbsp;self = [self initInManagedObjectContext:nil withScoreKeeper:nil withWordList:nil];\n&nbsp;&nbsp;&nbsp;&nbsp;return self;\n}\n- (instancetype)initWithCoder:(NSCoder *)aDecoder {\n&nbsp;&nbsp;&nbsp;&nbsp;NSAssert(NO, @&quot;%@&quot;, @&quot;Tried to implement with initWithCoder&quot;);\n&nbsp;&nbsp;&nbsp;&nbsp;self = [self initInManagedObjectContext:nil withScoreKeeper:nil withWordList:nil];\n&nbsp;&nbsp;&nbsp;&nbsp;return self;\n}\n<\/code><\/pre><br \/>\nNow I get this error in the log when I try to call initWithStyle directly.<br \/>\n<pre><code class=\"preserve-code-formatting\">\n*** Assertion failure in -[SettingsTableViewController initWithStyle:], \/Users\/jscarry\/Words\/Words\/Settings\/SettingsTableViewController.m:37\n<\/code><\/pre><\/p>\n<p><a href=\"http:\/\/stackoverflow.com\/questions\/26185239\/ios-designated-initializers-using-ns-designated-initializer\">This<\/a> stackoverflow question has some useful info.<\/p>\n<p><a href=\"http:\/\/useyourloaf.com\/blog\/2014\/08\/19\/xcode-6-objective-c-modernization.html\"> This article<a\/> explains more about why it is implemented. <\/p>\n<p>Update: I found this article (<a href=\"http:\/\/petersteinberger.com\/blog\/2015\/uitableviewcontroller-designated-initializer-woes\/\">UITableViewController Designated Initializer Woes<\/a>) where they have a more complete explanation of the issue and a more complete fix.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I programmatically create several tables and the code has worked fine for years. It did not generate any warnings two weeks ago when I last ran it. I\u2019ve since updated to Xcode 8.3 and 10.10.3 and now get three warnings for each UITableViewController. Method override for the designated initializer of the superclass &#039;-initWithStyle:&#039; not found. &hellip; <a href=\"https:\/\/www.wellgolly.com\/?p=2222\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">NS_DESIGNATED_INITIALIZER warnings<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[],"class_list":["post-2222","post","type-post","status-publish","format-standard","hentry","category-ios"],"_links":{"self":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2222"}],"version-history":[{"count":0,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2222\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}