inputAccessoryView hides after UIViewController view disappears - ios

I implemented docked inputAccessoryView like this:
lazy var inputView: UIView = {
// custom creation
}()
override var inputAccessoryView: UIView? {
return inputView
}
override var canBecomeFirstResponder: Bool {
return true
}
It works almost great, the issue is that inputView hides after I dismiss UIViewController (it is visible for 1 second, and then disappears).

Related

Embedding a UIScrollView inside of a UIPageViewController and disabling pageView swiping?

I have a UIView subclass (a graph) embedded inside of a UIScrollview inside of a UIViewController which is one of a UIPageViewControllers pages... I'm trying to disable scrolling of the UIPageViewController so that the user scan scroll to see the far left of the graph without paging back. How can I do this? Is a ScrollView even the correct tool for this job?
class HistoricalHealthDataViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var graphScrollView: UIScrollView!
#IBOutlet weak var hockeyTrackerGraphView: HockeyTrackerGraphView! {
didSet {
self.hockeyTrackerGraphView.graphableObjects = HFRGraphableObjects
}
}
var HFRGraphableObjects: [HockeyTrackerGraphableObject] = []
override func viewDidLoad() {
super.viewDidLoad()
graphScrollView.delegate = self
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let parentPageViewController = parent as? HistoricalPageViewController {
for gestureRecognizer in parentPageViewController.gestureRecognizers {
print("gestureRecognizer")
gestureRecognizer.isEnabled = false
}
}
}
}
You don't show the code for it, but I'm assuming you implement UIPageViewControllerDataSource protocol and somewhere you have the methods:
func pageViewController(UIPageViewController, viewControllerBefore: UIViewController) -> UIViewController? {
}
func pageViewController(UIPageViewController, viewControllerAfter: UIViewController) -> UIViewController? {
}
If you arrange for those methods to return nil while paging is disabled, the page view won't scroll to a different page.

IOS Swift how can I include the search function inside another function

I have 2 Controllers and one is a SubView. The MainController has access to the SearchBar property and the SubViewController does not . There is a SearchBar function in the Main Controller that I would like to invoke in the SubView Controller it is this function
// MainController
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
// Stop doing the search stuff
// and clear the text in the search bar
searchBar.text = ""
// Hide the cancel button
searchBar.showsCancelButton = false
searchBar.endEditing(true)
Popup.Close_View()
}
What I am trying to do is wrap that function above in another function like this
func Selected_Location() {
searchBarCancelButtonClicked(SearchBar)
}
so that in my SubView Controller I can do
// SubView Controller
let Select_Close = MainController()
Select_Close.Selected_Location()
I am new to Swift and as stated before how can I get the searchBarCancelButtonClicked function and call it inside another function with ? I have tried doing it in several ways such as
func Selected_Location() {
searchBarCancelButtonClicked(_ searchBar: UISearchBar)
}
func Selected_Location() {
searchBarCancelButtonClicked(searchBar)
}
Again my SubView Controller does not have access to a UISearchBar so I am trying to call the SearchBar close function from within the SubView.
In Subview, keep weak reference of MainViewController, and then call one method of mainviewcontroller searchBarCancel
class MainViewController:UIViewController {
var subViewController: SubViewController
func searchBarCancel(){
searchBarCancelButtonClicked(self.searchBar)
}
func func2(){
subViewController.mainController = self
}
}
class SubViewController:UIView {
weak var mainController: MainViewController?
func Selected_Location() {
mainController!.searchBarCancel()
}
}

SubView click item to show in parent view label

I would like to make a UI that have label, table view and one button click. When click on the button, we pop up a half screen view that have lots of buttons. I want user can still click on the rest of the screen also.
So i use the approach that suggest in the post
How To Present Half Screen Modal View?
Method 2: to animate a UIView which is of size half of the existing view.
Then you have to simply follow animation of the UIView.
Here as it is just a UIView that will be added as subview to existing view, you will be able to touch the rest of the screen.
As i am newbie to the ios and swift, I would like to get some suggestions.
Now i am successfully add as subview and show in the half of the screen.
How can i implement to let subview click button result show on parent view label text?
I am thinking about parent.xib and subview.xib have the same UIVeiwController.swift. Then i can #IBOutlet and #IBAction to the same controller swift file and update the result. But don't know it is the accpetable way to do?
If not, how can the subViewController send result/event to the parent view and update in the parent view component?
You could use delegation. This keeps your view controllers decoupled, i.e. prevents the child from having a reference to its parent, which allows other view controllers to interact with the modal view controller in the same way.
class ParentViewController : UIViewController, ModalViewControllerDelegate {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let modalViewContorller = ModalViewController()
modalViewContorller.delegate = self
self.presentViewController( modalViewContorller, animated: true, completion: nil )
}
func modalViewControllerDidProduceResult( modalViewController: ModalViewController, result: String ) {
self.label.text = result
}
}
protocol ModalViewControllerDelegate {
func modalViewControllerDidProduceResult( modalViewController: ModalViewController, result: String )
}
class ModalViewController: UIViewController {
var delegate: ModalViewControllerDelegate?
#IBAction func buttonClicked( sender: AnyObject? ) {
delegate?.modalViewControllerDidProduceResult( self, result: "Hello!" )
}
}
You could also use a closure, which in Swift provides a more concise syntax.
class ParentViewController : UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let modalViewContorller = ModalViewController()
self.presentViewController( modalViewContorller, animated: true, completion: nil )
modalViewContorller.resultBlock = { (result: String) in
self.label.text = result
}
}
}
class ModalViewController: UIViewController {
var resultBlock: ((String) -> ())?
#IBAction func buttonClicked( sender: AnyObject? ) {
self.resultBlock?( "Hello!" )
}
}

Display inputAccessoryView in childViewController

I have a parent view controller that acts as a container for a UIPageViewControllerand another UIViewController (called commentsViewController). I want to show the inputAccessoryView inside the commentsViewController however it doesn't seem to be working. I have added the commentsViewController to the parent like so:
commentsViewController = storyboard!.instantiateViewControllerWithIdentifier("CommentsViewController")! as! CommentsViewController
self.addChildViewController(commentsViewController)
self.view.addSubview(commentsViewController.view)
//...I have set some autolayout constraints here
commentsViewController.didMoveToParentViewController(self)
Then inside CommentsViewController, I have the following:
#IBOutlet var customView: UIView!
override var inputAccessoryView: UIView {
return customView
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
self.becomeFirstResponder()
}
Unfortunately this doesn't work and the inputAccessoryView is not displayed... Can anyone see what I'm missing?
Thank you.
Turns out that because I was animating the view, becomeFirstResponder() automatically returned false. After the animation it works fine.

When creating a UIViewController that doesn't take up the full screen, how do I dismiss it by tapping outside?

I'm following this tutorial to make a overlay view controller, using frameOfPresentedViewInContainerView in iOS 8, but I'm curious, how would I then close this view controller based on tapping outside of the visible area?
There is one popular solution where you add a UITapGestureRecognizer to the window and then perform a hit test to check if the tap was outside the modal view frame.
However, since you use UIPresentationController, I'd suggest going for the more versatile solution:
In your UIPresentationController subclass override presentationTransitionWillBegin:
override func presentationTransitionWillBegin() {
var dimView = UIView() // Use your specific subclass here
dimView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.5) // No need for this if you have your subclass defined in IB
self.containerView?.addSubview(dimView)
dimView.snp_makeConstraints { (make) -> Void in // I use SnapKit to avoid the NSLayoutConstraint nonsense
make.edges.equalTo(self.containerView!)
}
dimView.addSubview(self.presentedViewController.view)
let transitionCoordinator = self.presentedViewController.transitionCoordinator()
dimView.alpha = 0
transitionCoordinator?.animateAlongsideTransition({ (context) -> Void in
dimView.alpha = 1
}, completion: { (context) -> Void in
})
}
This will give you a proper dimming view that will be placed behind your presented view controller. Now it's totally up to you what you do with that dimming view, you can style it or place buttons there:
I recommend defining this view in the interface builder, it makes it a lot easier, the example may look like this:
class MyDimView: UIView {
var onPrevAction: (() -> ())?
var onNextAction: (() -> ())?
var onTapAction: (() -> ())?
#IBOutlet private var prevButton: UIButton!
#IBOutlet private var nextButton: UIButton!
#IBOutlet private var button: UIButton!
#IBAction private func onPrevButtonTouched() {
if let prevAction = self.onPrevAction {
prevAction()
}
}
#IBAction private func onNextButtonTouched() {
if let nextAction = self.onNextAction {
nextAction()
}
}
#IBAction private func onViewTouched() {
if let tapAction = self.onTapAction {
tapAction()
}
}
}
This way you have the absolute control over what happens outside or your presented view controller.

Resources