MMDrawerController Subclass in Swift - ios

if you're using Swift + CocoaPods + use_frameworks! with the MMDrawerController opened source (ObjC) library you might have trouble subclassing MMDrawerController getting multiple warnings of "unused initializer"
All you'll have to do is override the initializers and call super. Pretty easy but I saw that there was absolutely nothing on this issue while Googling for this issue, so I'm just trying to help out. I've posted my code below.

import UIKit
import MMDrawerController
class TRDrawerController: MMDrawerController {
private var recordsModel = TRRecordsModel.sharedInstanceOfRecordsModel
private var itemsModel = TRItemsModel.sharedInstanceOfItemsModel
init() {
let centerViewController = UIStoryboard(name: "TRMain", bundle: nil).instantiateViewControllerWithIdentifier("TRTrackerViewController") as! TRTrackerViewController
centerViewController.recordsModel = recordsModel
centerViewController.itemsModel = itemsModel
let firstNavigationController = TRNavigationController(rootViewController: centerViewController)
let rightViewController = UIStoryboard(name: "TRMain", bundle: nil).instantiateViewControllerWithIdentifier("TRSettingsViewController") as! TRSettingsViewController
rightViewController.recordsModel = recordsModel
centerViewController.itemsModel = itemsModel
let secondNavigationController = TRNavigationController(rootViewController: rightViewController)
super.init(centerViewController: firstNavigationController, leftDrawerViewController: nil, rightDrawerViewController: secondNavigationController)
self.openDrawerGestureModeMask = [.PanningCenterView]
self.closeDrawerGestureModeMask = [.PanningCenterView, .TapCenterView, .TapNavigationBar]
self.shouldStretchDrawer = false
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
// Won't be utilizing this, I want the app to crash if this gets used
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

Related

How to write custom UIViewController initialiser with property in Swift?

I am trying to write my own UIVC initializer:
let person: Person
init(withPerson person: Person) {
self.person = person
super.init()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
but in my coordinator I have this line:
func getViewController() -> UIViewController? {
return ViewController(nibName: "ViewController", bundle: Bundle.main)
}
and it causes a crash with error:
Fatal error: Use of unimplemented initializer 'init(nibName:bundle:)' for class 'ViewController'
when I try to add:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
it rises an error with:
Property 'self.person' not initialized at super.init call
is there a way how I can fix the crash?
init(withPerson person: Person) {
self.person = person
super.init (nibName: "ViewController", bundle: Bundle.main)
}
You have to call super.init(nibName:bundle:) instead of super.init() as it's a designated initializer.
If you specify nil for the nibName parameter and you do not override the loadView() method, the view controller searches for a nib file as described here.
init(withPerson person: Person) {
self.person = person
super.init(nibName: nil, bundle: nil)
}

Instance of a class only returning nil

Fairly new to swift, and struggling with creating an instance of a class within another class. I'm firing a notification and then in my app delegate it responds by playing the music player and changing label in my viewController, but when it tries to change the label app crashes with error "Unexpectedly found nil while implicitly unwrapping an Optional value". I can get round it by adding a '?' but why is it getting nil.
Code
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, AVAudioPlayerDelegate {
var musicPlayerManager: MusicPlayerManager = MusicPlayerManager()
var viewController: ViewController = ViewController()
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
//show an alert window
var playlistName: String = ""
if let userInfo = notification.userInfo {
playlistName = userInfo["soundName"] as! String
}
musicPlayerManager.playPlaylist(chosenPlaylist: playlistName)
print(playlistName)
viewController.currentPlaylist.text = "Playlist: \(playlistName)"
}
}
I'm getting the playlistName printed in the console, and then it crashes with the last line suggesting that it's an issue with the instance of viewController, and my attempt to change the label in the view controller from the app delegate.
Outlets are nil until vc loads also you need to load it from storyboard if it exists there
viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "id") as! ViewController
viewController.view.layoutIfNeeded()
viewController.currentPlaylist.text = "Playlist: \(playlistName)"
If you don't want to use storyboard you can create your ViewController in this structure. But you need to add your Subview(currentPlaylist) into your view and also need to set it's frame
import UIKit
class ViewController: UIViewController {
let currentPlaylist = UILabel()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init() {
super.init(nibName: nil, bundle: nil)
currentPlaylist.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
view.addSubview(currentPlaylist)
}
}

How do I initialise view controller with custom data?

I'm using present to open a view controller.
self.storyboard = UIStoryboard(name: "myStoryboard", bundle: nil)
self.myView = self.storyboard?.instantiateInitialViewController() as? myViewController
self.present(self.myView!, animated: true) { _ in }
Then in the view controller I'm trying to get data from initialiser
class myViewController: UIViewController {
var dataA: String?
var dataB: String?
override init(dataA: String, dataB: String) {
self.dataA = dataA
self.dataB = dataB
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
I get an error Initializer does not override a designated initializer from its superclass
How should I override init and pass data in this case?
I do not think there is a way, other than not using storyboards. Even Swinject does that in a separate method.
class myViewController: UIViewController {
var dataA: String?
var dataB: String?
fun initialize(dataA: String, dataB: String) {
self.dataA = dataA
self.dataB = dataB
}
}
and in the other class
self.storyboard = UIStoryboard(name: "myStoryboard", bundle: nil)
self.myView = self.storyboard?.instantiateInitialViewController() as? myViewController
self.myView.initialize(dataA: dataA, dataB: dataB)
self.present(self.myView!, animated: true) { _ in }
or you can do it in other way and create a static func, that will return an instance. But I prefer the first way.
class myViewController: UIViewController {
var dataA: String?
var dataB: String?
static func instance(dataA: String, dataB: String) -> myViewController {
//You could pass storyboard too
let storyboard = UIStoryboard(name: "myStoryboard", bundle: nil)
let myView = storyboard.instantiateInitialViewController() as? myViewController
self.dataB = dataB
self.dataA = dataA
return myView
}
}

Custom init UIViewController query

I am hoping you can help me understand why the below code segment works and the other does not. I am wanting to create a custom initialiser for my UIViewController which has a custom nib file I have created.
My issue is that I want to understand why in the below code the references to newMember and facebookLogin are retained when I hit the viewDidLoad method but in the other segment of code they are not? Can anyone shed some light as to why this would be the case?
Working Code Block
class RegistrationFormViewController: MiOSBaseViewController
{
var newMember:Member!
var facebookLogin: Bool = false
init(member: Member, facebookLogin: Bool = false) {
self.newMember = member
self.facebookLogin = facebookLogin
super.init(nibName: "RegistrationFormViewController", bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(nibName: "RegistrationFormViewController", bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
let view = self.view as! RegistrationFormView
view.loadViewWith(member: newMember)
view.customNavBarView.backActionBlock = {
self.newMember.deleteEntity(MiOSDataContext.sharedInstance.managedObjectContext)
_ = self.navigationController?.popViewController(animated: true)
return
}
}
}
Broken Code Block
class RegistrationFormViewController: MiOSBaseViewController
{
var newMember:Member!
var facebookLogin: Bool = false
init(member: Member, facebookLogin: Bool = false) {
self.newMember = member
self.facebookLogin = facebookLogin
super.init(nibName: "RegistrationFormViewController", bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
let view = self.view as! RegistrationFormView
view.loadViewWith(member: newMember)
view.customNavBarView.backActionBlock = {
self.newMember.deleteEntity(MiOSDataContext.sharedInstance.managedObjectContext)
_ = self.navigationController?.popViewController(animated: true)
return
}
}
}
Thanks,
Michael

Why passed value is nil in viewcontroller

I know this is simple question but I couldn't understand for hours what's the problem here.
enum TypeOfAlert {
case success, error, warning, confirm
}
class MainAlertView: UIViewController {
var mode: TypeOfAlert!
var transitioner : CAVTransitioner
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
self.transitioner = CAVTransitioner()
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.modalPresentationStyle = .custom
self.transitioningDelegate = self.transitioner
setupAlertView()
}
private func setupAlertView() {
print(mode) // result is nil
}
convenience init() {
self.init(nibName:nil, bundle:nil)
}
required init?(coder: NSCoder) {
fatalError("NSCoding not supported")
}
}
I have this code to show alertdialog
I opening MainAlertView by pressing a button
let vc = IFOMainAlertView()
vc.delegate = self
vc.mode = TypeOfAlert.confirm
self.present(vc,animated: true)
but when I am printing or debuging var mode is always nil. Why ?
You have printed var mode before you set it
you are trying to debug at initialisation moment,
when you called
let vc = IFOMainAlertView()
the function init was called, before you called the rest:
vc.delegate = self
vc.mode = TypeOfAlert.confirm
either add a new constructor to your class that takes mode as an argument, or delay debugging the mode attribute to the viewDidLoad method

Resources