Instantiate UIViewController from Storyboard, viewDidLoad() not executed - uiviewcontroller

I'm creating a Slideout navigation controller.
Now I need to assign my MenuViewController and my TopViewController.
I have a TopViewController screen in a Storyboard that was using other type of slideout menu.
In my AppDelegate I have the following:
let storyboard : UIStoryboard! = UIStoryboard(name: "Main", bundle: nil)
let dashboard = storyboard.instantiateViewControllerWithIdentifier("DashboardView") as! DashboardViewController
let menu : SlideoutViewController = SlideoutViewController()
menu.menuEnabled = true
menu.topView = dashboard
menu.menuView = SalesViewController()
UIApplication.sharedApplication().keyWindow?.rootViewController = menu as SlideoutViewController
But when doing this the viewDidLoad method in DashboardViewController is never reached, that means that the view has not been instantiated yet.
Any clue?
UPDATE: this is a function selectView in slideout view controller
func selectView(viewController: UIViewController){
if (_internalTopNavigation != nil)
{
_internalTopNavigation!.removeFromParentViewController();
_internalTopNavigation!.view.removeFromSuperview();
}
_internalTopNavigation = UINavigationController(rootViewController: viewController)
_internalTopNavigation!.view.frame = CGRect(x: 0, y: 0,
width: _internalTopView!.view.frame.width,
height: _internalTopView!.view.frame.height)
_currentView = viewController;
_internalTopView!.addChildViewController(_internalTopNavigation!);
_internalTopView!.view.addSubview(_internalTopNavigation!.view);
if (_menuEnabled == true)
{
viewController.navigationItem.leftBarButtonItem = createMenuButton()
viewController.navigationItem.leftBarButtonItem!.tintColor = UIColor.blueColor()
}
_externalContentView = viewController;
}

Related

Swift wkwebview is not showing fullscreen

I am a beginner of Swift and trying to develop web view app
the website in the web view have popups , so I also put some code for pop up
but when I run this app ,the screen is like that picture below
I tried
"mainView = WKWebView(frame : UIScreen.main.bounds
,configuration: configuration)"
then this app shows full screen but does not show tool bar
could you guys help me what I should try ...
here is codes
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
preferences.javaScriptCanOpenWindowsAutomatically = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
mainView = WKWebView(frame :
CGRect.init(x: 0, y: 0, width: self.mainView.frame.size.width, height: self.mainView.frame.size.height)
,configuration: configuration)
mainView.uiDelegate = self
mainView.navigationDelegate = self
view.addSubview(mainView)
self.webViews.append(self.mainView)
let mainURL = URL(string: url)
let mainRequest = URLRequest(url: mainURL!)
self.mainView.load(mainRequest)
func webView(_ webView: WKWebView,
createWebViewWith configuration: WKWebViewConfiguration,
for navigationAction: WKNavigationAction,
windowFeatures: WKWindowFeatures
) -> WKWebView? {
guard let frame = self.webViews.last?.frame else {
return nil
}
return createWebView(frame: frame, configuration: configuration)
}
func createWebView(frame: CGRect, configuration: WKWebViewConfiguration) -> WKWebView {
var webView = WKWebView(frame: frame, configuration: configuration)
print("createWebView ")
// set delegate
// webView = WKWebView(frame: frame, configuration: configuration)
// webView.autoresizingMask = [.flexibleWidth , .flexibleHeight]
webView.navigationDelegate = self
webView.uiDelegate = self
webView.scrollView.alwaysBounceVertical = false
webView.scrollView.bounces = false
self.view.addSubview(webView)
self.webViews.append(webView)
return webView
}

Present tab bar controller based on a set of conditions

In, one of my multiple UIViewControllers, I have a sign in button that takes you to a tab bar scene. The viewcontrollers shown in the tab bar scene depends on the type of account selected. In another scene, there's a button which updates it's titlelabel based on type of account. Here is what I have done.
class SIgn_In: UIViewController {
let tabbar = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func didTapSignIn(_ sender: Any) {
guard let vc = storyboard?.instantiateViewController(identifier: "vc") as? AccountViewController else{return}
let firstVc = First()
let secondVc = Second()
let thirdVc = Third()
if vc.text == "accountType1" {
tabbar.setViewControllers([firstVc,secondVc], animated: false)
} else if vc.text == "accounttype2" {
tabbar.setViewControllers([thirdVc,firstVc,secondVc], animated: false)
}
present(tabbar,animated: true)
}
In the accountViewController, I have this code.
class AccountViewController: UIViewController {
#IBOutlet weak var button: UIButton!
public var accountType:String = ""
override func viewDidLoad() {
super.viewDidLoad()
accountType = button.currentTitle!
}
But I'm not quite getting what I expected, what am I missing? Please help

Buttons and some user interactions are not responding with iOS14 app

I am struggling with a strange bug with my iOS app. When using a simulator with iOS 13 application works as it should, but when using iOS 14 buttons, switches, and other functionalities are not responding. There is no error output in the console.
I don't understand why this happens only with XCode 11 and iOS 14.
This a snippet with initializing one of my buttons in the View.
let logButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setLogInButton()
button.setTitle(NSLocalizedString("log_in", comment: ""), for: .normal)
return button
}()
Here I'm assigning the target to the button.
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
initConstraints()
backgroundColor = UIColor().settingsTableViewCellColor()
logButton.addTarget(self, action: #selector(buttonLogInLogOut), for: .touchUpInside)
}
There is the action
#objc func buttonLogInLogOut(_ sender: UIButton){
print("Log in clicked")
delegate?.logInLogOutFunc(sender)
}
As I said the buttons (switches, and others) are not responding ONLY in iOS 14.
It looks like targetActions are not working.
Thanks for any kind of help.
Regards
Matt
I had the same problem with a button in a table cell not working
For some reason you have to add the button to the contentView of the cell instead of the cell itself as follows
cell.contentView.addSubView(button)
Worked for me afterwards
Just follow this solution
For Cell:
class CommentCell: UICollectionViewCell {
private let commentViewCell: CommentViewCell = {
let view = CommentViewCell()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(commentViewCell)
NSLayoutConstraint.activate([
commentViewCell.leadingAnchor.constraint(equalTo: leadingAnchor),
commentViewCell.trailingAnchor.constraint(equalTo: trailingAnchor),
commentViewCell.topAnchor.constraint(equalTo: topAnchor),
commentViewCell.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setData(item: CommentViewModel) {
commentViewCell.setData(item: item)
}
}
For View:
class CommentViewCell: UIView {
private let lblId: CustomClick = {
let view = CustomClick()
view.backgroundColor = .cyan
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let lblMessage: UILabel = {
let view = UILabel()
view.backgroundColor = .cyan
view.textColor = .black
view.font = .boldSystemFont(ofSize: 16)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let lblDate: UILabel = {
let view = UILabel()
view.backgroundColor = .systemIndigo
view.textColor = .black
view.font = .boldSystemFont(ofSize: 16)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .brown
addSubview(lblId)
addSubview(lblMessage)
addSubview(lblDate)
NSLayoutConstraint.activate([
lblId.topAnchor.constraint(equalTo: topAnchor),
lblId.trailingAnchor.constraint(equalTo: trailingAnchor),
lblId.leadingAnchor.constraint(equalTo: leadingAnchor),
lblMessage.trailingAnchor.constraint(equalTo: trailingAnchor),
lblMessage.leadingAnchor.constraint(equalTo: leadingAnchor),
lblMessage.topAnchor.constraint(equalTo: lblId.bottomAnchor),
lblDate.trailingAnchor.constraint(equalTo: trailingAnchor),
lblDate.leadingAnchor.constraint(equalTo: leadingAnchor),
lblDate.topAnchor.constraint(equalTo: lblMessage.bottomAnchor),
])
lblId.addTarget(self, action: #selector(onClick), for: .touchUpInside)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func onClick() {
print("this is click button")
}
func setData(item: CommentViewModel) {
lblId.setData(item: item.id)
lblMessage.text = item.meesage
lblDate.text = item.date
lblDate.textColor = item.cellColor
}
class CustomClick: UIControl {
private let lblId: UILabel = {
let view = UILabel()
view.textColor = .black
view.backgroundColor = .systemPink
view.font = .boldSystemFont(ofSize: 16)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(lblId)
NSLayoutConstraint.activate([
lblId.topAnchor.constraint(equalTo: topAnchor),
lblId.trailingAnchor.constraint(equalTo: trailingAnchor),
lblId.leadingAnchor.constraint(equalTo: leadingAnchor),
lblId.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setData(item: String) {
lblId.text = item
}
}
}

Share JSON Data in TabBarController to view controllers

I am using a tabbarcontroller to show 3 xib's. I would like to decode JSON data in the UITabBarController subclass, and then share the data with the view controllers (as I understand that is the preferred way to do this). I had already successfully accomplished this individually in each view controller, where the same JSON data was getting decoded separately 3 times, but I am now trying to make the process more efficient by only dealing with JSON once.
I am currently getting the following error
"Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee7ab7d98)".
Below is the code I am currently using. I'm mostly only including the code for the first view controller, but it is the same for the others
Here is one of the view controllers. Any help would be appreciated, thank you!
class FirstCollectionViewController: UIViewController {
var tbvc = CustomTabBar()
var statisticsData = [Model]()
let firstCellIdentifier = "FirstCellIdentifier"
#IBOutlet weak var FirstCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
FirstCollectionView.delegate = self
FirstCollectionView.dataSource = self
FirstCollectionView.register(UINib(nibName: "FirstCollectionViewCell", bundle: nil),forCellWithReuseIdentifier: firstCellIdentifier)
}
}
Here is the subclasses UITabBarController
import UIKit
class CustomTabBar: UITabBarController {
let website = "https:......."
var statisticsData = [Model]()
override func viewDidLoad() {
super.viewDidLoad()
let firstTab = FirstCollectionViewController(nibName: "FirstCollectionViewController", bundle: nil)
let secondTab = SecondCollectionViewController(nibName: "SecondCollectionViewController", bundle: nil)
let thirdTab = ThirdCollectionViewController(nibName: "ThirdCollectionViewController", bundle: nil)
viewControllers = [firstTab, secondTab, thirdTab]
downloadJSON(website: website) {
firstTab.statisticsData = self.statisticsData
secondTab.statisticsData = self.statisticsData
thirdTab.statisticsData = self.statisticsData
firstTab.FirstCollectionView.reloadData()
secondTab.SecondCollectionView.reloadData()
thirdTab.ThirdCollectionView.reloadData()
}
}
func downloadJSON(website:String, completed:#escaping ()->()){
guard let qurl = URL(string: website) else { return }
URLSession.shared.dataTask(with: qurl) { (data, response, error) in
if error == nil {
do{
self.statisticsData = try JSONDecoder().decode([Model].self, from: data!)
DispatchQueue.main.async{
completed()
}
} catch {
print("JSON Error")
}}
}.resume()
}
}
Once the data is loaded, you should assign the data to the viewControllers that are added in the tabBarController's Child list as below,
downloadJSON(website: website) {
firstTab.statisticsData = self.statisticsData
secondTab.statisticsData = self.statisticsData
thirdTab.statisticsData = self.statisticsData
firstTab.FirstCollectionView.reloadData()
secondTab.SecondCollectionView.reloadData()
thirdTab.ThirdCollectionView.reloadData()
}
You can also remove the below lines from viewDidLoad of FirstCollectionViewController, SecondCollectionViewController and ThirdCollectionViewController
tbvc = tabBarController as! CustomTabBar
statisticsData = tbvc.statisticsData

Access to tabbar Controller from AppDelegate

I have this situation:
How can I access the 3rd Tab bar badge from AppDelegate?
I've used this code:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UIViewController *vc = [[UIViewController alloc] init];
if ([nonLette isEqualToString:#"0"]) {
for (vc in tabBarController.viewControllers) {
if (vc.tabBarItem.tag == 999) {
vc.tabBarItem.badgeValue = nil;
}
}
but the self.window.rootViewController returns "start View" and so does not work.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabController = storyboard.instantiateViewController(withIdentifier: "TabBarViewController") as! TabBarViewController
let tabArray = tabController.tabBar.items as NSArray!
let alertTabItem = tabArray?.object(at: 3) as! UITabBarItem
alertTabItem.badgeValue = "10"
Ok, I'm resolved, but in part!!!
This method works well. With debug, I can see that now I can change the badge on desired tab, but in reality don't change in graphics (the red number not appear).
Some suggestion?
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *myTabBarController = [storyboard instantiateViewControllerWithIdentifier:#"tabBarController"];
if ([nonLette isEqualToString:#"0"]) {
for (UIViewController *vc in myTabBarController.viewControllers) {
if (vc.tabBarItem.tag == 999) {
vc.tabBarItem.badgeValue = nil;
}
}
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
} else {
for (UIViewController *vc in myTabBarController.viewControllers) {
if (vc.tabBarItem.tag == 999) {
vc.tabBarItem.badgeValue = nonLette;
}
}
[UIApplication sharedApplication].applicationIconBadgeNumber=[result integerValue];
}
With the new XCode 11 and Swift 5 this is no longer possible.
Instead you want to do this in SceneDelegate.swift, in particular this function func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
You then want to do something like this.
self.window = self.window ?? UIWindow()//#JA- If this scene's self.window is nil then set a new UIWindow object to it.
//#Grab the storyboard and ensure that the tab bar controller is reinstantiated with the details below.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
self.window!.rootViewController = tabBarController //Set the rootViewController to our modified version with the StateController instances
self.window!.makeKeyAndVisible()
print("Finished scene setting code")
guard let _ = (scene as? UIWindowScene) else { return }
Hope this helps for the people using the newer XCode out there. The key here is appDelegate no longer has access to window, the sceneDelegate does. If you try to use appDelegate you will get an error that window no longer exists.
Make sure the identifier is set for the tabBarController in the storyboard so it can find it. You can name it whatever, but just refer to that name in the code here for the withIdentifier function