How to to set action backBarButtonItem and still display left arrow?
I used this code but the arrow was not display
var barBack = UIBarButtonItem(title: "Reset", style: UIBarButtonItemStyle.Plain, target: self, action: "reset:")
self.navigationItem.leftBarButtonItem = barBack
but when I used this code the action not working
self.navigationController?.navigationBar.topItem?.backBarButtonItem = barBack
Thanks
As an alternative to setting an action, you can keep the backBarButtonItem and use isMovingFromParentViewController instead to handle logic for moving back on the navigation stack.
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParentViewController() {
.. do something here
}
}
Try this
var barBack = UIBarButtonItem(title: "Reset", style: UIBarButtonItemStyle.Plain, target: self, action: "reset:")
self.navigationItem.leftBarButtonItem = barBack
Let me know if it works.
Try this:
In ViewDidLoad
let backButton = UIBarButtonItem(title: "< Home", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
navigationItem.leftBarButtonItem = backButton
navigationItem.backBarButtonItem?.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "the_font_you_want_to_use", size: size_of_the_font_this_should_be_integer)!], forState: UIControlState.Normal)
and implement the following method:
func goBack() {
self.navigationController?.popToRootViewControllerAnimated(boolean)
}
Just replace the the_font_you_want_to_use, size_of_the_font_this_should_be_integer and boolean with the values you want, and everything will be working.
*** EDIT
If you don't want to get back to Root View Controller, instead of
self.navigationController?.popToRootViewControllerAnimated(boolean)
you can say:
self.navigationController?.popViewControllerAnimated(boolean)
or even pop to some other ViewController with specifying the first parameter of the popToViewController to be the object of YourViewController class, and second the boolean value for animation.
Related
I have a background image that I would like to expand when clicked. I have setup animations that will dim the background and prop the image to the center, but for some reason the image is not clickable.
I have tried to implement a simple print(tapped) and when I tap I dont see anything as well. I am wondering if I have to declare my image view as something else?
import Foundation
import UIKit
class JobViewController: UIViewController {
let imageView: UIImageView = {
let iv = UIImageView(image: #imageLiteral(resourceName: "yo"))
iv.contentMode = .scaleAspectFill
iv.isUserInteractionEnabled = true
iv.translatesAutoresizingMaskIntoConstraints = false
iv.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleZoomTap)))
return iv
}()
#objc func handleZoomTap(_ tapGesture: UITapGestureRecognizer) {
print("tap tap")
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
imageView.fillSuperview()
}
}
When I tap the image, I expect that it should at least print "tap tap"
Is there something else that i am missing?
Delete this line:
iv.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleZoomTap)))
And add this to your viewDidLoad:
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleZoomTap)))
well before i ask this i try the other solutions and it didn't work
this is my code
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: "didTouchBoard:")
view.addGestureRecognizer(tapGesture)
tapGesture.cancelsTouchesInView = true
}
when i click anywhere it will hide the keyboard if exist , but if i click on tableviewcell or collectionviewcell , it won't click
i try this tapGesture.cancelsTouchesInView , but not work
If you want table view to receive touch, then change tapGesture.cancelsTouchesInView
tapGesture.cancelsTouchesInView = false
You have to add the UITextFeildDelegate methods to enable and disable tap gesture in the view
declare tapGesture outside the view did load method
let tapGesture = UITapGestureRecognizer(target: self, action: "didTouchBoard:")
implement the following methods
func textFieldDidBeginEditing(textField: UITextField) {
self.view.addGestureRecognizer(self.tapGesture) }
func textFieldDidEndEditing(textField: UITextField) {
self.view.removeGestureRecognizer(self.tapGesture)
}
i think that might work for you
I'm creating a keyboard extension in XCode Beta 7 (Swift2).
I'm trying to connect multiple buttons to a single action.
However, when I connect all the button outlets to this action, it causes my keyboard to crash which makes me think there's something I'm missing.
#IBOutlet weak var Label: UIButton!
#IBAction func ButtonTapped(sender: AnyObject) {
Label.setTitle("Hello!", forState: .Normal)
Label.hidden = false
Label.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "hideLabel", userInfo: nil, repeats: false)
}
#objc func hideLabel() {
Label.hidden = true
Label.backgroundColor = UIColor.clearColor()
}
Attaching the same action to multiple buttons is not a problem, and is a common technique.
However, you have Label set as force-unwrapped, which will crash if it is nil.
My guess is that your Label outlet is not connected so Label is nil at runtime.
Change the type of Label from UIButton! to UIButton? and then change your code to use "if let" optional binding to only execute the code using Label if label is non-nil.
BTW, Swift has a strong naming convention. Variable names should start with a lower-case letter and use "camel case" for the rest of the variable name. Only class names and type names should start with a capital letter. So "Label" should be "label" instead. Get in the habit of following that style. It serves as a clear visual cue to you and others reading your code as to what type of thing a name refers to.
Finally, "Label" is a horrible name for a button. It's a button, not a UILabel. Call it "myButton" or something instead.
EDIT
The code might look like this:
#IBOutlet weak var myButton: UIButton?
#IBAction func ButtonTapped(sender: AnyObject)
{
println("myButton = \(myButton)") //See if myButton is nil
if let myButton = myButton
{
myButton.setTitle("Hello!", forState: .Normal)
myButton.hidden = false
myButton.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self,
selector: "hidemyButton",
userInfo: nil, repeats: false)
}
}
#objc func hidemyButton()
{
myButton.hidden = true
myButton.backgroundColor = UIColor.clearColor()
}
I am working on Xcode 6.1.1 on OSX 10.10. I am trying out storyboards for Mac apps. I have a NSTabViewController using the new NSTabViewControllerTabStyleToolbar tabStyle and it is set as the default view controller for the window controller. How do I make my window resize according to the current selected view controller?
Is it possible to do entirely in Interface Builder?
Here is what my storyboard looks like:
The auto layout answer is half of it. You need to set the preferredContentSize in your ViewController for each tab to the fitting size (if you wanted the tab to size to the smallest size satisfying all constraints).
override func viewWillAppear() {
super.viewWillAppear()
preferredContentSize = view.fittingSize
}
If your constraints are causing an issue below try first with a fixed size, the example below sets this in the tab item's view controller's viewWillAppear function (Swift used here, but the Objective-C version works just as well).
override func viewWillAppear() {
super.viewWillAppear()
preferredContentSize = NSSize(width: 400, height: 280)
}
If that works, fiddle with your constraints to figure out what's going on
This solution for 'toolbar style' tab view controllers does animate and supports the nice crossfade effect. In the storyboard designer, add 'TabViewController' in the custom class name field of the NSTabViewController. Don't forget to assign a title to each viewController, this is used as a key value.
import Cocoa
class TabViewController: NSTabViewController {
private lazy var tabViewSizes: [String : NSSize] = [:]
override func viewDidLoad() {
// Add size of first tab to tabViewSizes
if let viewController = self.tabViewItems.first?.viewController, let title = viewController.title {
tabViewSizes[title] = viewController.view.frame.size
}
super.viewDidLoad()
}
override func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions, completionHandler completion: (() -> Void)?) {
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.5
self.updateWindowFrameAnimated(viewController: toViewController)
super.transition(from: fromViewController, to: toViewController, options: [.crossfade, .allowUserInteraction], completionHandler: completion)
}, completionHandler: nil)
}
func updateWindowFrameAnimated(viewController: NSViewController) {
guard let title = viewController.title, let window = view.window else {
return
}
let contentSize: NSSize
if tabViewSizes.keys.contains(title) {
contentSize = tabViewSizes[title]!
}
else {
contentSize = viewController.view.frame.size
tabViewSizes[title] = contentSize
}
let newWindowSize = window.frameRect(forContentRect: NSRect(origin: NSPoint.zero, size: contentSize)).size
var frame = window.frame
frame.origin.y += frame.height
frame.origin.y -= newWindowSize.height
frame.size = newWindowSize
window.animator().setFrame(frame, display: false)
}
}
The window containing a toolbar style tab view controller does resize without any code if you have auto layout constraints in your storyboard tab views (macOS 11.1, Xcode 12.3). I haven't tried other style tab view controllers.
If you want to resize with animation as in Finder, it is sufficient to add one override in your tab view controller. It will resize the window with system-calculated resize animation time and will hide the tab view during resize animation:
class PreferencesTabViewController: NSTabViewController {
override func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions = [], completionHandler completion: (() -> Void)? = nil) {
guard let window = view.window else {
super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
return
}
let fromSize = window.frame.size
let toSize = window.frameRect(forContentRect: toViewController.view.frame).size
let widthDelta = toSize.width - fromSize.width
let heightDelta = toSize.height - fromSize.height
var toOrigin = window.frame.origin
toOrigin.x += widthDelta / 2
toOrigin.y -= heightDelta
let toFrame = NSRect(origin: toOrigin, size: toSize)
NSAnimationContext.runAnimationGroup { context in
context.duration = window.animationResizeTime(toFrame)
view.isHidden = true
window.animator().setFrame(toFrame, display: false)
super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
} completionHandler: { [weak self] in
self?.view.isHidden = false
}
}
}
Please adjust closure syntax if you are using Swift versions older than 5.3.
Use autolayout. Set explicit size constraints on you views. Or once you have entered the UI into each tab view item's view set up the internal constraints such that they force view to be the size you want.
(Xcode6, iOS8, Swift, iPad)
I am trying to create a classic Web-like modal view, where the outside of the dialog box is "grayed-out." To accomplish this, I've set the alpha value of the backgroundColor of the view for the modal to 0.5, like so:
self.view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.5)
The only problem is that when the modal becomes full-screen, the presenting view is removed. (Ref Transparent Modal View on Navigation Controller).
(A bit irritated at the concept here. Why remove the underlying view? A modal is, by definition, to appear atop other content. Once the underlying view is removed, it's not really a modal anymore. it's somewhere between a modal and a push transition. Wa wa wa... Anyway..)
To prevent this from happening, I've set the modalPresentationStyle to CurrentContext in the viewDidLoad method of the parent controller, and in Storyboard... but no luck.
self.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
self.navigationController.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
How do I prevent the presenting view from being removed when the modal becomes full screen?
tyvm.. more info below.
Also in Storyboard, like so (Presentation: Current Context)
Thx for your help... documentation below:
First, remove all explicit setting of modal presentation style in code and do the following:
In the storyboard set the ModalViewController's modalPresentation style to Over Current context
Check the checkboxes in the Root/Presenting ViewController - Provide Context and Define Context.
They seem to be working even unchecked.
You can try this code for Swift:
let popup : PopupVC = self.storyboard?.instantiateViewControllerWithIdentifier("PopupVC") as! PopupVC
let navigationController = UINavigationController(rootViewController: popup)
navigationController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
self.presentViewController(navigationController, animated: true, completion: nil)
For swift 4 latest syntax using extension:
extension UIViewController {
func presentOnRoot(`with` viewController : UIViewController){
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
self.present(navigationController, animated: false, completion: nil)
}
}
How to use:
let popup : PopupVC = self.storyboard?.instantiateViewControllerWithIdentifier("PopupVC") as! PopupVC
self.presentOnRoot(with: popup)
The only problem I can see in your code is that you are using CurrentContext instead of OverCurrentContext.
So, replace this:
self.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
self.navigationController.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
for this:
self.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
self.navigationController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
This worked for me in Swift 5.0. Set the Storyboard Id in the identity inspector as "destinationVC".
#IBAction func buttonTapped(_ sender: Any) {
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let destVC = storyboard.instantiateViewController(withIdentifier: "destinationVC") as! MyViewController
destVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
destVC.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
self.present(destVC, animated: true, completion: nil)
}
The problem with setting the modalPresentationStyle from code was that you should have set it in the init() method of the presented view controller, not the parent view controller.
From UIKit docs: "Defines the transition style that will be used for this view controller when it is presented modally. Set
this property on the view controller to be presented, not the presenter. Defaults to
UIModalTransitionStyleCoverVertical."
The viewDidLoad method will only be called after you already presented the view controller.
The second problem was that you should use UIModalPresentationStyle.overCurrentContext.
The only way I able to get this to work was by doing this on the presenting view controller:
func didTapButton() {
self.definesPresentationContext = true
self.modalTransitionStyle = .crossDissolve
let yourVC = self.storyboard?.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
let navController = UINavigationController(rootViewController: yourVC)
navController.modalPresentationStyle = .overCurrentContext
navController.modalTransitionStyle = .crossDissolve
self.present(navController, animated: true, completion: nil)
}
I am updating a simple solution. First add an id to your segue which presents modal. Than in properties change it's presentation style to "Over Current Context". Than add this code in presenting view controller (The controller which is presenting modal).
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let Device = UIDevice.currentDevice()
let iosVersion = NSString(string: Device.systemVersion).doubleValue
let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8
if((segue.identifier == "chatTable")){
if (iOS8){
}
else {
self.navigationController?.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
}
}
}
Make sure you change segue.identifier to your own id ;)