I am trying to change tab bar in didFinishLaunchingWithOptions method programmatically, but it won't work, any idea?
I have tried:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let tabBarController = self.window!.rootViewController as? UITabBarController {
tabBarController.selectedIndex = 0
}
return true
}
Thanks,
are you sure that your root view controller is UITabBarController?
because it would seem that you do not enter the if-let.
It's possibile that you've a navigation controller that contains your tab viewcontroller?
Related
This question already has answers here:
Pass data back to previous viewcontroller
(9 answers)
Closed 3 years ago.
I have a question about Sending the value back to the main page
After login-> Page 1-> page2-> press home button -> page 1
When I go, there is no problem with the delivery. But I want to press the home button and return the value to page1
this out put on page 2
pShipmentDCBeforeLoad==>Optional("4505023274")
pPlanDateDCBeforeLoad==>Optional("20190119")
TruckIdDCBeforeLoad==>Optional("2")
ptruckNoDCBeforeLoad==>Optional("60-7624")
pShipmentDCBeforeLoad==>Optional("4505023274")
See from the picture
After login -> page 1 -> go to page 2
this code on page 2
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Check segue identifier
if segue.identifier == "gotoAfterLoadingDC" {
// Get SecondVC
let destinationVC = segue.destination as! AfterLoadViewController
// Pass text to SecondVC
destinationVC.pShipmentDCAfterLoad = pShipmentDCBeforeLoad!
destinationVC.pPlanDateDCAfterLoad = pPlanDateDCBeforeLoad!
destinationVC.TruckIdDCAfterLoad = TruckIdDCBeforeLoad!
destinationVC.ptruckNoDCAfterLoad = ptruckNoDCBeforeLoad
destinationVC.PlanDetailIdDCAfterLoad = PlanDetailIdDCBeforeLoad!
}
}
press Home button on page 2 -> go to page 1
#IBAction func BacktoPlandata(_ sender: UIBarButtonItem) {
DispatchQueue.main.async {
//self.performSegue(withIdentifier: "BeforeloadBacktoplandata", sender: "self")
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Back to home
if segue.identifier == "BeforeloadBacktoplandata" {
//Get SecondVC
let destinationVC = segue.destination as! PlanDataViewController
//Pass text to SecondVC
destinationVC.getpShipmentPickerView.text! = self.pShipmentDCBeforeLoad!
destinationVC.getpPlanDatePickerView.text! = self.pPlanDateDCBeforeLoad!
destinationVC.ptruckidDCPlanData = self.TruckIdDCBeforeLoad!
destinationVC.ptruckNoDCPlanData = self.ptruckNoDCBeforeLoad
destinationVC.pPlandDetailIdDCPlanData = self.PlanDetailIdDCBeforeLoad!
// Show log back to plandata
print("pShipmentDCBeforeLoad==>\(String(describing: self.pShipmentDCBeforeLoad))")
print("pPlanDateDCBeforeLoad==>\(String(describing: self.pPlanDateDCBeforeLoad))")
print("TruckIdDCBeforeLoad==>\(String(describing: self.TruckIdDCBeforeLoad))")
print("ptruckNoDCBeforeLoad==>\(String(describing: self.ptruckNoDCBeforeLoad))")
print("pShipmentDCBeforeLoad==>\(String(describing: self.pShipmentDCBeforeLoad))")
// call fuction
print("//////////////-getPlanDetail-BacktoPlandata-/////////////////")
self.getPlanDetailDCbeforeLoadingViewController(pshipment: self.pShipmentDCBeforeLoad!, pplanDate: self.pPlanDateDCBeforeLoad!)
}
}
}
}
Seems you can create method in Home screen with data you want to pass as a parameter and call it from Page 2.
In Home screen
func someData(param1: String, param2: String) { }
From Page 2
let destinationVC = segue.destination as! PlanDataViewController
destinationVC.someData(param1: "ABC", param2: "XYZ")
Also, you can pass data by creating property in home screen and passing data from Page2.
Instead of using segue you can use navigationController controller and it will get the same instance of page 1 (VC) that is already loaded into navigation controller. If you use the segue it will create new instance that will present on the top of page 2 (VC). So instead of using new instance use the same instance that is created already.
#IBAction func BacktoPlandata(_ sender: UIBarButtonItem) {
let n: Int! = self.navigationController?.viewControllers?.count
let destinationVC = self.navigationController?.viewControllers[n-1] as! UIViewController
destinationVC.getpShipmentPickerView.text! = self.pShipmentDCBeforeLoad!
destinationVC.getpPlanDatePickerView.text! = self.pPlanDateDCBeforeLoad!
destinationVC.ptruckidDCPlanData = self.TruckIdDCBeforeLoad!
destinationVC.ptruckNoDCPlanData = self.ptruckNoDCBeforeLoad
destinationVC.pPlandDetailIdDCPlanData = self.PlanDetailIdDCBeforeLoad!
self.navigationController.popViewController(animated: true)
}
You could try post notification which send your data once you click the home button,
NotificationCenter.default.post(name: Notification.Name(rawValue: "anyname"), object: ["TruckID": self.TruckIdDCBeforeLoad])
In the home controller add this in viewdidload,
NotificationCenter.default.addObserver(self, selector: #selector(refresh(_:)), name: NSNotification.Name(rawValue: "anyname"), object: nil)
https://www.hackingwithswift.com/example-code/system/how-to-post-messages-using-notificationcenter
https://learnappmaking.com/notification-center-how-to-swift/
I'm new at swift and i can not find how to how to refresh TableView and JSON datas same time. First refresh Json after refresh TableView. How can I do this ?
You need to add pull to refresh class to your UITableView
private let refreshControl = UIRefreshControl()
var tableView: UITableView!
Then in ViewDidLoad add it as a subview to your tableView and you can even change its color and text.
override func viewDidLoad() {
if #available(iOS 10.0, *) {
tableView.refreshControl = refreshControl
} else {
tableView.addSubview(refreshControl)
}
refreshControl.tintColor = UIColor.blue
refreshControl.attributedTitle = NSAttributedString(string: "Fetching Data ...", attributes: [NSAttributedStringKey.foregroundColor : UIColor(red:0/255, green:168/255, blue:225/255, alpha:1.0)])
refreshControl.addTarget(self, action: #selector(refreshData(_:)), for: .valueChanged)
}
Add a target to it with a selector function when value changes as shown above.
#objc private func refreshData(_ sender: Any) {
//load the data from the server and
//parse and put it in an array then reload your table view
}
I have a UIViewController with UIWebViewDelegate. I found that I can present it just fine but not push it. If I try to push it the target view controller loads and executes any variables set but does not fire viewDidLoad() and instead just returns to my calling menu view controller without error.
I set a breakpoint on the first var declaration after the class and stepped through the code. When it got to webView init it flashed up the home (not target) view controller in the simulator and then continued though the var declarations before returning back to my home view controller.
Here is my menu code
works:
let myWebViewController = MyWebViewController()
myWebViewController.urlString = "myUrl"
present(myWebViewController, animated: true, completion: nil)
does not work
let myWebViewController = MyWebViewController()
myWebViewController.urlString = "myUrl"
let navController = (UIApplication.shared.delegate as! AppDelegate).navController
navController!.pushViewController(myWebViewController, animated: true)
Here is my redacted target view controller code. The URL to load is set in the menu.
import UIKit
class MyWebViewController: UIViewController, UIWebViewDelegate {
var urlString: String = "invalid url"
var url: URL {
return URL(string: urlString)!
}
var urlRequest: URLRequest {
var urlRequest = URLRequest(url: url)
return urlRequest
}
let webView: UIWebView = {
let view = UIWebView()
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// declare various buttons and stack views
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
contentStackView.addArrangedSubview(webView)
mainStackView.addArrangedSubview(contentStackView)
view.addSubview(mainStackView)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
webView.loadRequest(urlRequest as URLRequest)
}
The problem has nothing to do with the web view, the web view controller, or anything else except where you're pushing the view controller. You are saying:
let navController = (UIApplication.shared.delegate as! AppDelegate).navController
navController!.pushViewController(myWebViewController, animated: true)
That is highly unusual. The usual thing is that we are inside a navigation interface already, and we push onto its stack:
let navController = self.navigationController
navController!.pushViewController(myWebViewController, animated: true)
But you are not saying that. Why not? I'm guessing it's because self does not have a navigationController. So you are successfully pushing onto the navigation controller, all right, but you are not seeing anything happening because the navigation controller is behind the scenes — the self view controller's view is blocking it or has replaced it.
And that explains why you never detect the url loading. Your call to webView.loadRequest is in viewWillAppear. But this view will not appear; it is behind the scenes. viewWillAppear is never called. Similarly viewDidLoad is not called, because this view is not going to load; the navigation controller is not occupying the interface — self is.
I could possibly think of one scenario why the webViewController is not being pushed.
The UIViewController from which you are trying to make the push might not be part of the navigation controller hierarchy.
Why don't you try using the code instead of getting the navController from AppDelegate
self.navigationController?.pushViewController(myWebViewController, animated: true)
If this doesn't work out then your are certainly doing something wrong.
In App Delegate:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask(rawValue: UIInterfaceOrientationMask.landscape.rawValue)
}
In my View Controller(MainViewController) I have added
override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
supportedInterfaceOrientations()
preferredInterfaceOrientationForPresentation()
// Do any additional setup after loading the view.
}
private func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask(rawValue: UIInterfaceOrientationMask.portrait.rawValue)
}
private func shouldAutorotate() -> Bool {
return true
}
private func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
// Only allow Portrait
return UIInterfaceOrientation.portrait
}
This is the only controller in the application that I want to work in portrait mode. except this everything in Landscape mode.
But I've tried numerous things still unable to understand why is it not working.
Thanks in advance. Sorry for being noob in swift.
write this code in appdelegate
var shouldRotate = false
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if shouldRotate {
return .landscape
}
else {
return .portrait
}
}
set this code to your view controller in viewDidload()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.shouldRotate = true // or false to disable rotation
//you can manage only changing true or false
hope its helps you
I would like to add the quick actions of iOS 9 to my app.
I put this code in my app delegate:
import UIKit
enum ShortcutType: String {
case NewScan = "QuickAction.NewScan"
case Settings = "QuickAction.Settings"
}
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
static let applicationShortcutUserInfoIconKey = "applicationShortcutUserInfoIconKey"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UIViewController.prepareInterstitialAds()
if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) {
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil))
}
// QUICK ACTIONS
var launchedFromShortCut = false
if #available(iOS 9.0, *) {
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
launchedFromShortCut = true
handleShortCutItem(shortcutItem)
}
} else {
return true
}
return !launchedFromShortCut
}
/**************** QUICK ACTIONS ****************/
#available(iOS 9.0, *)
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -> Void) {
let handledShortCutItem = handleShortCutItem(shortcutItem)
completionHandler(handledShortCutItem)
}
#available(iOS 9.0, *)
func handleShortCutItem(shortcutItem: UIApplicationShortcutItem) -> Bool {
var handled = false
if let shortcutType = ShortcutType.init(rawValue: shortcutItem.type) {
let rootNavigationViewController = window!.rootViewController as? UINavigationController
let rootViewController = rootNavigationViewController?.viewControllers.first as UIViewController?
rootNavigationViewController?.popToRootViewControllerAnimated(false)
switch shortcutType {
case .NewScan:
rootViewController?.performSegueWithIdentifier("goToCamera", sender: nil)
handled = true
case.Settings:
rootViewController?.performSegueWithIdentifier("goToSettings", sender: nil)
handled = true
}
}
return handled
}
}
Now I can make a force touch on my app icon > quick actions will be shown > I select the Quick Action "New Scan" > the app will open and show me the last view, which I have leave.
But the segue will not be execute.
Here is a part of my storyboard:
Explanation:
A: Navigation Controller and initiale Controller
B: ViewController, after a check this will make a segue to navigation Controller C
C: Navigation Controller
D: Table View Controller
E: ViewController
If I select New Scan with quick actions - I would like to show ViewController E.
It appears that you're doing things correctly based on the example code in the documentation. However, you've got a lot of optional chaining in your handleShortCutItem: implementation. Have you used the debugger to verify none of those expression have nil values? Also, from what I can see (although the image is blurry), the root view controller of the first nav controller in that storyboard does not have a segue to E. So I'm not sure how you intend to get there.
I would suggest that you set a breakpoint in your handleShortCutItem: implementation to first validate that the values you're working with are not nil and the code is actually executing. Once you've done this, you can use your storyboard to instantiate the view controls you want and just create an array of them as you want your view controller hierarchy to be in your navigation controller and set the navigation controller's viewControllers property to this array. Again, it's hard to tell exactly what you want from your image, but perhaps something like this:
func handleShortCutItem(shortcutItem: UIApplicationShortcutItem) -> Bool {
guard let shortcutType = ShortcutType.init(rawValue: shortcutItem.type) else {
return false
}
guard let rootNavigationController = window?.rootViewController as? UINavigationController else {
return false
}
guard let rootViewController = rootNavigationController?.viewControllers.first else {
return false
}
guard let storyboard = rootNavigationController.storyboard else {
return false
}
var viewControllers = [rootViewController]
switch shortcutType {
case .NewScan:
// Instantiate the necessary view controllers for this case
viewControllers += [storyboard.instantiateViewControllerWithIdentifier("<#Identifier for some view controller#>")]
...
viewControllers += [storyboard.instantiateViewControllerWithIdentifier("<#Identifier for some other view controller#>")]
case.Settings:
// Instantiate the necessary view controllers for this case
viewControllers += [storyboard.instantiateViewControllerWithIdentifier("<#Identifier for some view controller#>")]
...
viewControllers += [storyboard.instantiateViewControllerWithIdentifier("<#Identifier for some other view controller#>")]
}
// Set the new view controllers array
rootNavigationController.setViewControllers(viewControllers, animated: false)
return true
}
Note: Since you tagged this question with Swift2, I've taken the liberty of adjusting the code to use guard statements.