Instance of a class only returning nil - ios

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)
}
}

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)
}

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

Unable to retrieve view controller with NSProgressIndicator programatically

I am trying to retrieve the actual view controller and call a method to change the ProgressIndicator.
I have the following function in my AppDelegate
func applicationDidFinishLaunching(_ aNotification: Notification) {
let main = NSStoryboard(name: "Main", bundle: Bundle.main)
let vc = main.instantiateController(withIdentifier: "Installing") as! ViewController
vc.incrementBar(number: 20)
}
The incrementBar function is as follows
#IBOutlet weak var progressView: NSProgressIndicator!
public func incrementBar(number: Double){
if(self.progressView != nil){
print(number)
self.progressView.increment(by: number)
}
}
Just to be sure. I can easily call this function from viewDidLoad() or viewDidAppear() but as soon as i try to receive the actual controller it tells me that progressView is nil

Why is the data not being saved?

I am getting a fatal error: unexpectedly found nil while unwrapping an Optional value when I am trying to open a notification onto a certain view controller. I think I know why, there are some variables which are nil, causing the app to crash, but I am trying to give those variables data, but they are not saving.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
let text = userInfo["aps"]!["alert"]
let title = userInfo["aps"]!["alert"]!!["title"]
let artist = userInfo["aps"]!["alert"]!!["artist"]
print(text)
print(title)
print(artist)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("PlayerController") as! PlayerViewController
vc.dataModel.artistplay = artist as? String
vc.dataModel.titleplay = title as? String
window?.rootViewController = vc
}
This is the code for the PlayerViewController (The view controller I am trying to open when the push notification is opened)
#IBOutlet weak var playertitle: UILabel!
#IBOutlet weak var playerartist: UILabel!
var dicData : NSDictionary?
var dataModel : DataModelTwo?
var data: NSDictionary?
var shareDataModel: Share?
var buttonState: Int = 0;
override func viewWillAppear(animated: Bool) {
playertitle.text = dataModel!.titleplay
playerartist.text = dataModel!.artistplay
}
do NOT set UILable text from AppDelegate.
set a variable in your ViewController then use it in viewDidLoad.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
let text = userInfo["aps"]!["alert"]
print(text)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("PlayerController") as! PlayerViewController
vc.foo = "bar"
window?.rootViewController = vc
}
use variables and update UI :
override func viewDidLoad() {
print(self.foo) // output is "bar"
}
From the code you show, the dataModel in PlayerViewController is not initialized and, as it is an optional, its value is nil. Since you're implicitly unwrapping - dataModel! it causes the crash.
Initialize first the dataModeland then use it to get the values you want.

MMDrawerController Subclass in Swift

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")
}
}

Resources