I am receiving an error message:
fatal error: init(coder:) has not been implemented
For my custom UITableViewCell
. The cell is not registered, has the identifier cell in the storyboard and when using dequeasreusablecell. In the custom cell I have the inits as:
Code:
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
print("test")
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
But I still have the error. Thanks.
Huy Nguyen
2,0253 gold badges25 silver badges35 bronze badges
asked Aug 16, 2016 at 4:14
2
Replace your init with coder method:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Actually if you have your cell created in Storyboard — I believe that it should be attached to tableView on which you try to create it. And you can remove both of your init methods if you do not perform any logic there.
UPD:
If you need to add any logic — you can do this in awakeFromNib() method.
override func awakeFromNib() {
super.awakeFromNib()
//custom logic goes here
}
tanz
2,54720 silver badges31 bronze badges
answered Aug 16, 2016 at 4:17
ruslan.musagitovruslan.musagitov
2,0842 gold badges12 silver badges14 bronze badges
5
Firstly, you need to call the super class’ init(coder:)
method with the statement super.init(coder: aDecoder)
. You do that by adding
it right under the method signature like-
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Secondly, you need to remove the statement,
fatalError("init(coder:) has not been implemented")
.
That should work.
answered May 3, 2019 at 4:29
NatashaNatasha
6,5331 gold badge34 silver badges55 bronze badges
I have this class file for accepting card payments
import UIKit
class PaymentViewController: UIViewController , PTKViewDelegate {
var card : STPCard
var PaymentView : PTKView
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
init(PaymentView : PTKView , button : UIButton, card : STPCard) {
self.PaymentView = PaymentView
self.button = button
self.card = card
super.init()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
When I build it, it works fine, but when I execute it (run it) on my actual device , I get
fatal error: init(coder:) has not been implemented.
Any ideas ?
MoralCode
1,8671 gold badge19 silver badges42 bronze badges
asked Oct 28, 2014 at 16:06
5
Based on the Inheritance Hierarchy you have setup. PaymentViewController
will inherit 3 init methods.
UIViewController
provides init(nibName:bundle)
as its designated initializer.
UIViewController
also conforms to NSCoding
which is where the required init(coder:)
comes from.
UIViewController
also inherits from NSObject
which provides a basic init()
method.
The problem you are having stems from init(coder:
being called when the ViewController is instantiated from a .xib or storyboard. This method is called to un-archive the .xib/storyboard objects.
From the Documentation:
iOS initializes the new view controller by calling its initWithCoder: method instead.
You should be calling the superclass designated initializer in your init
method, which is init(nibName:bundle)
Note: it is fine for both of those parameters to be nil. Also your init(coder:)
override should call super.init(coder:)
answered Oct 28, 2014 at 17:34
JMFRJMFR
7796 silver badges18 bronze badges
3
A simple workaround will do:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
answered Feb 26, 2017 at 12:26
BrightBright
5,5792 gold badges49 silver badges70 bronze badges
1
I’m trying to access another class in my CollectionView Controller but when I try and initialise the class I get the error
Here is the class
@MainActor
class AlbumsViewModel {
private let albumService: AlbumService
private let favouritesService: FavouritesService
private let recommendationService: RecommendationService
@Published var favourites = [Bool]()
@Published var recommendedAlbums = [Album]()
@Published var allAlbums = [Album]() {
didSet {
updateFavourites()
}
}
init(albumService: AlbumService, favouritesService: FavouritesService, recommendationService: RecommendationService) {
self.albumService = albumService
self.favouritesService = favouritesService
self.recommendationService = recommendationService
}
...(functions here)
Collectionview Controller Class
class CVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var viewModel: AlbumsViewModel
init?(viewModel: AlbumsViewModel, coder: NSCoder) {
self.viewModel = viewModel
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delaysContentTouches = false
Task {
print(viewModel.allAlbums)
}
} // End viewDidLoad
...
Trying to recreate this https://martinmitrevski.com/2021/07/11/ml-recommendation-app-with-create-ml-on-ios-15/
Accepted Reply
You are instantiating the CVC directly from your Storyboard.
So you can’t pass in the viewModel property.
You will have to think of another way to use viewModel in CVC.
For example, as a global singleton, like this…
In AlbumsViewModel:
static let shared = AlbumsViewModel(albumService:favouritesService:recommendationService:) // however you initialise it
…then in CVC, refer to
AlbumsViewModel.shared
…or create a shortcut property
let viewModel = AlbumsViewModel.shared
Replies
You have defined CVC init(coder:) to throw a fatal error.
You don’t show where you are initializing the CVC…
…but it seems that init(coder:) is being called, since you are seeing the error.
You need to implement a proper init(coder:)…
required init?(coder: NSCoder) {
super.init(coder: coder)
/// any other setup action here... what about viewModel?
}
… or use your custom initializer instead.
You should add at least super.init and remove fatal error.
What I often do is define a sharedInit() func that I call in all init, including coder.
self.sharedInit()
You are instantiating the CVC directly from your Storyboard.
So you can’t pass in the viewModel property.
You will have to think of another way to use viewModel in CVC.
For example, as a global singleton, like this…
In AlbumsViewModel:
static let shared = AlbumsViewModel(albumService:favouritesService:recommendationService:) // however you initialise it
…then in CVC, refer to
AlbumsViewModel.shared
…or create a shortcut property
let viewModel = AlbumsViewModel.shared
] (f7e1c44709ce595200c0c20a804217d5.jp/p>
Now I’m making my first app, and I’m displaying a list of articles like the picture above. Tap an article to see the details of the article. When you click the favorite button, the button color changes. I am trying to make an application that can switch between the article list and the favorite article list with the toolbar below.
When the favorite button is clicked, the reaml database is checked. If the id of the article is included, «remove» is not included. In addition, I am trying to write a code considering the design pattern with MVP for studying.
class ArticleTableViewController: UITableViewController {
var articles: [Article] = [] // array containing articles
...
override func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let article = articles [indexPath.row]
let vc = UIStoryboard (name: "ArticleContent", bundle: nil) .instantiateInitialViewController ()! as! ArticleContentViewController
vc.article.id = article.id
vc.article.content = article.content
self.navigationController? .pushViewController (vc, animated: true)
// pass id and article content to ArticleCOntentViewController
}
}
import RealmSwift
class RMArticle: Object {
@objc dynamic var id: Int = 0
@objc dynamic var content: String = ""
}
protocol ArticleView: class {
func updateFavoriteButtonTitle (_ title: String)
}
class ArticleContentViewController: UIViewController, ArticleView {
let article = RMArticle ()
private let presenter: ArticlePresenter
@IBOutlet weak var favorite: UIButton!
init (article: RMArticle, favoritePresenter: FavoritePresenter) {
self.presenter = ArticleViewPresenter (article: article, favoritePresenter: favoritePresenter)
super.init (nibName: nil, bundle: nil)
self.presenter.view = self
}
required init? (coder aDecoder: NSCoder) {
fatalError ("init (coder :) has not been implemented")
}
override func viewDidLoad () {
super.viewDidLoad ()
print (article.id)
print (article.content)
// Do any additional setup after loading the view.
}
As mentioned above, RMArticle instance has member variables id and content, receives the value in that instance, and later saves this instance in realm when saving. (When you actually display an article, specify the id and hit the API, so you don’t need to save the content, but you don’t know where to define the content …)
When I tap the article with this code,Thread 1: Fatal error: init (coder :) has not been implemented
is displayed.
required init? (coder aDecoder: NSCoder) {
Super.init (coder: aDecoder)
fatalError ("init (coder :) has not been implemented")
}
If i do the above, you will be toldProperty'self.presenter'not initialized at super.init call
. I think it has been initialized …
I didn’t understand the cause well, so I asked a question. Thank you.
Swift’s strict initialization rules are great. They help prevent an entire category of bugs that were especially common in Objective-C. However, when working with Objective-C frameworks, particularly UIKit
, these rules can be frustrating.
When you subclass UIViewController
and UIView
and provide your own initializer, the compiler will prompt you to add the following required
initializer:
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
For view controllers, init(nibName:bundle:)
is the designated initializer, but init(coder:)
is required by the NSCoding
protocol. It must be implemented not only because of the protocol, but because this is the initializer that Interface Builder calls when automatically instantiating UIViewController
subclasses from storyboards or xibs. The same applies to UIView
subclasses.
However, if you do not use Interface Builder, then init(coder:)
is irrelevant and will never be called. It is annoying boilerplate. But the real problem is that Xcode (and presumably other editors) will offer init(coder:)
as an auto-complete option when initializing your view or view controller. That is not ideal, because it is not a valid way to initialize your custom view or view controller. Luckily, you can use Swift’s @available
attribute to prevent this, which also has the benefit of more clearly communicating that you should not use this initializer.
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("(#function) has not been implemented")
}
Now, at compile-time, this initializer is inaccessible. Or technically, at “auto-complete while you type time”.
You might have the idea of putting this in an extension or a protocol, so that you can avoid typing the boilerplate for every UIView
and UIViewController
subclass. Unfortunately, that is not possible because required
initializers must be provided in subclass declarations. So, using @available
is the best we can do.
UPDATE: Thanks to JP for pointing out that there’s a SwiftLint rule for exactly this. Unfortunately, it does not currently support autocorrect.