How to use the BottomNavigationController with SideNavigationController - cosmicmind

I would like to use the SideNavigationController (SlideOutBar) with a BottomNavigationController (BottomNavigationController)
My usecase is similar to the "App" in the examples, "Recipes". When tapping on "Recipes" there is a table with tabs at the bottom. My use case I would like "Recipes A", "Recipes B", "Recipes C" etc... on the sidebar in which updates the main view with different combinations of tabs or a view with no tabbar.
I'm a bit confused how switch out these combinations from the SideBarNavigation. In my app delegate I have:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("mainViewController") as! MainViewController
let sideViewController = storyboard.instantiateViewControllerWithIdentifier("sideViewController") as! SideViewController
let scratchPadViewController = storyboard.instantiateViewControllerWithIdentifier("scratchPadViewController") as! ScratchPadViewController
bottomNavigationController.viewControllers = [mainViewController, scratchPadViewController]
bottomNavigationController.selectedIndex = 0
bottomNavigationController.tabBar.tintColor = MaterialColor.teal.base
bottomNavigationController.tabBar.backgroundColor = MaterialColor.grey.darken4
// Configure the window with the SideNavigationController as the root view controller
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = SideNavigationController(rootViewController: bottomNavigationController, leftViewController: sideViewController)
window?.makeKeyAndVisible()
In my SideBar case 0 a new combination of tabs,case 1 with be just one controller and no tabs, case 3 original set of tabs, etc... How do I transition with clicking the item on the sidebar? Do I create a new bottomNavigationController and then set that? do I update the existing one?
switch indexPath.row {
case 0:
//NEW COMBINATION OF TABS
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("mainViewController") as! MainViewController
let blueViewController = storyboard.instantiateViewControllerWithIdentifier("blueViewController") as! BlueViewController
getAppDelegate().bottomNavigationController.setViewControllers([mainViewController, blueViewController], animated: true)
//remove scan button
mainViewController.hasScanButton = false
mainViewController.hasTabbar = true
//sideNavigationController?.closeLeftView()
//sideNavigationController?.transitionFromRootViewController(getAppDelegate().bottomNavigationController)
//sideNavigationController?.transitionFromRootViewController(getAppDelegate().bottomNavigationController,
duration: 1,
options: .TransitionNone,
animations: nil,
completion: { [weak self] _ in
self?.sideNavigationController?.closeLeftView()
})
case 1:
//place terminal
let mainViewController = storyboard!.instantiateViewControllerWithIdentifier("mainViewController") as! MainViewController
//remove scan button
mainViewController.hasScanButton = false
mainViewController.hasTabbar = false
sideNavigationController?.transitionFromRootViewController(mainViewController,
duration: 1,
options: .TransitionNone,
animations: nil,
completion: { [weak self] _ in
self?.sideNavigationController?.closeLeftView()})
default:
break
}
Thanks

Related

App crash when delete cell Item with custom Button (CoreData)

When i'm delete cell from my CollectionView app is crashed (CoreData).
I'm use custom button in CollectionView.
var cardItems = [NSManagedObject]()
cell.MenuButton.layer.setValue(indexPath.row, forKey: "index")
cell.MenuButton.addTarget(self, action: #selector(MenuCell), for: UIControl.Event.touchUpInside)
Error
EDIT (It's work)
let i: Int = (sender.layer.value(forKey: "index")) as! Int
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let indexPath = IndexPath(item: i, section: 0)
let itemToDelete = self.cardItems[indexPath.item]
self.cardItems.remove(at: indexPath.item)
managedContext.delete(itemToDelete)
appDelegate.saveContext()
self.collectionView.reloadData()
First of all, it's not a good way to identify the click button. Instead, you can set button tag as indexPath.row like below:
menuButton.tag = indexPath.row
cell.MenuButton.layer.setValue(indexPath.row, forKey: "index")
Also improve your coding skills see below:
cell.MenuButton.addTarget(self, action: #selector(onClickMenuButton(_:)), for: .touchUpInside)
Implement this selector as:
let i: Int = (sender.layer.value(forKey: "index")) as! Int
func onClickMenuButton(_ sender: UIButton) {
let task = self.cardItems[sender.tag]
if let managedContext = task.managedObjectContext {
managedContext.delete(task)
do {
try managedContext.save()
self.cardItems.remove(at: sender.tag)
let indexPath = IndexPath(row: i, section: 0)
self.collectionView.deleteItems(at: [indexPath])
} catch {
print("Failed to delete")
}
}
}
Your array indexPaths does not have any value. It is because there is no collection view items which are in selected state
You can select first collection view item programmatically as follows :
let indexPath = collectionView.indexPathsForSelectedItems?.first ?? IndexPath(item: 0, section: 0)
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: UICollectionView.ScrollPosition.centeredHorizontally)

How to make a customisable navigation bar title? Swift 4

I have a textfield on my firstViewController and what I want to happen is: once the user entered a text and goes to the SecondViewController it will become the navigation bar title.
I'm new at programming and I was hoping someone could help me.
First way to navigate creating object of view controller and navigate through navigation controller
let second = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
second.title = textTitle.text!
navigationController?.pushViewController(second, animated: true)
Second way to navigate from storyboard
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "segueIdentifier" else { return }
let destination = segue.destination as? SecondViewController
destination?.strTitle = textTitle.text!
}
In second view controller add this
var strTitle : String?
override func viewDidLoad() {
super.viewDidLoad()
self.title = strTitle ?? "default string"
}
Can you try #ChanWarde way but present the view controller rather than using segues ?
let second = storyboard?.instantiateViewController(withIdentifier:
"SecondViewController") as! SecondViewController
second.title = textTitle.text!
present(second, animated: true, completion: nil)
Or try:
let second = storyboard?.instantiateViewController(withIdentifier:
"SecondViewController") as! SecondViewController
second.title = textTitle.text!
DispatchQueue.main.async(execute: {
UIApplication.shared.keyWindow?.rootViewController = second()
self.dismiss(animated: true, completion: nil)
})

How do i add the Menu controller to any UiViewController , other than the rootview?

I am trying just to display the floating Menu on a separate view controller that is not the rootview ? Normally i just add it to the rootview controller.
let menuController = AppMenuController(rootViewController: toolbarController)
let navigationController = AppNavigationDrawerController(rootViewController: menuController, leftViewController: leftViewController,rightViewController: rightViewController)
let statusController = AppStatusBarController(rootViewController: navigationController)
window = UIWindow(frame: Screen.bounds)
window!.rootViewController = statusController
window!.makeKeyAndVisible()
let main: MainViewController = {
return UIStoryboard.viewController(identifier: "MainViewController") as! MainViewController}()
let newView = AppMenuController(rootViewController: main)
self.present(allergyView, animated: false, completion: nil)
Add the Menu as a property of the UIViewController. For example:
class ViewController: UIViewController {
fileprivate let menu = Menu()
fileprivate let baseSize = CGSize(width: 64, height: 64)
open override func viewDidLoad() {
super.viewDidLoad() {
prepareMenu()
}
}
extension MenuController {
fileprivate func prepareMenu() {
menu.zPosition = 1000
menu.baseSize = baseSize
view.layout(menu)
.size(baseSize)
.bottom(24)
.right(24)
}
}
In cases where you would not want to use the Material controllers with root view controllers, you should be able to look at the setup code in those controllers to see the code necessary to add the component they manage, for example MenuController.
All the best :)

Swift update existing item core data

I have seen many examples with one view controller for adding or updating core data items. Any thoughts on pros or cons of doing in separate view controllers?
My code for trying to do the update I think I am missing one key part to get it to work.
#IBAction func saveItem(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("Items", inManagedObjectContext: context)
var existingItem = dataModel.self
if (row > 0) {
println(teaname.text)
existingItem.setValue(teaname.text as String, forKey: "name")
existingItem.setValue(teatype.text as String, forKey: "type")
existingItem.setValue(qty.text as String, forKey: "amount")
existingItem.setValue(temp.text as String, forKey: "temp")
existingItem.setValue(time.text as String, forKey: "time")
} else {
}
context.save(nil)
self.navigationController?.popViewControllerAnimated(true)
}
I get (lldb) with a thread breakpoint at existingItem.setValue(teaname.text as String, forKey: "name")
It does not appear you actually have a specific object to update. I use the following function to fetch an object by its unique ID. Only once you have an object (mine is called Event) can you update it.
func fetchEvent(eventID: Int) -> Event? {
// Define fetch request/predicate/sort descriptors
var fetchRequest = NSFetchRequest(entityName: "Event")
let sortSections = NSSortDescriptor(key: "eTitle", ascending: true)
let sortDescriptor = NSSortDescriptor(key: "eID", ascending: true)
let predicate = NSPredicate(format: "eID == \(eventID)", argumentArray: nil)
var error = NSErrorPointer()
// Assign fetch request properties
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortSections, sortDescriptor]
fetchRequest.fetchBatchSize = 1
fetchRequest.fetchLimit = 1
// Handle results
let fetchedResults = managedObjectContext?.executeFetchRequest(fetchRequest, error: error)
if fetchedResults?.count != 0 {
if let fetchedEvent: Event = fetchedResults![0] as? Event {
println("Fetched object with ID = \(eventID). The title of this object is '\(fetchedEvent.eTitle)'")
return fetchedEvent
}
}
return nil
}
Once you have fetched an object and have a core data object to update, then you can update it like so.
func updateEvent(eventDict: Dictionary<String, AnyObject>, id: Int) {
if let event: Event = fetchEvent(id) {
println(event)
event.eID = id
event.eTitle = getString(eventDict["title"])
event.eLocation = getString(eventDict["location"])
event.eDescription = getString(eventDict["description"])
event.eStart = getDate(eventDict["startDate"])
event.eEnd = getDate(eventDict["endDate"])
event.eMod = NSDate()
event.eSecID = getSecID(event)
}
}
And then you may want to save your managed object context.

How do I detect Tap and Hold on a pin in MKMapView?

The title says it all. I'm trying to detect a tap on a pin in a MKMapView and I don't even know where to begin. Its not an UIView, so I can't add a gesture recognizer and I can't find a UIView in MKPlaceMark to add it.
You're question is not very clear but you can do like this:
import UIKit
import MapKit
protocol HandleMapSearch: class {
func dropPinZoomIn(placemark:MKPlacemark)
}
class ViewController: UIViewController {
func getDirections(){
// Here you can put anythings like:
guard let selectedPin = selectedPin else { return }
let mapItem = MKMapItem(placemark: selectedPin)
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
mapItem.openInMapsWithLaunchOptions(launchOptions)
}
}
extension ViewController : MKMapViewDelegate {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?{
guard !(annotation is MKUserLocation) else { return nil }
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
}
pinView?.pinTintColor = UIColor.orangeColor() // The pin's color
pinView?.canShowCallout = true // To set dialogue bubbles of the pin.
let smallSquare = CGSize(width: 30, height: 30)
let button = UIButton(frame: CGRect(origin: CGPointZero, size: smallSquare)) // To initialize the button in the dialogue bubbles of the pin.
button.addTarget(self, action: #selector(ViewController.getDirections), forControlEvents: .TouchUpInside) // To set and initialize the button.
pinView?.leftCalloutAccessoryView = button
return pinView
}
}
You can have more details in Thorn web site

Resources