The added UIBarButtonItem doesn't do any action - uibarbuttonitem

I want to change the UIBarButtonItem display, I can add a button without problem, but the added UIBarButtonItem doesn't do any action. Any one please help?
let leftBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action, target: self, action: #selector(sayHello))
func sayHello() {
print("Hello")
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.setLeftBarButton(leftBarButton, animated: true)
}

Related

UITapGestureRecognizer conflict with didSelectRowAtIndexPath

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

Why won't my Interstitial Ads work in my GameScene but work in the GameViewController in Swift?

I have these facebook interstitial ads and when I call them in my GameScene they dont show up. They work perfectly when I call them in the GameViewController but not in my GameScene. Can someone tell me what Im doing wrong with my code?
//GameViewController.swift
class GameViewController: UIViewController, FBInterstitialAdDelegate {
let interstitialFBAD: FBInterstitialAd = FBInterstitialAd(placementID: "65543456456456_454345345454534")
override func viewDidLoad() {
super.viewDidLoad()
}
//CALL THIS IN MY GAMESCENE.
func loadFBInterstitialAd() {
interstitialFBAD.delegate = self
interstitialFBAD.loadAd()
}
func interstitialAdDidLoad(interstitialAd: FBInterstitialAd!) {
interstitialFBAD.showAdFromRootViewController(self)
}
//GameScene.swift
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if node.name == "retry" {
GameViewController().loadFBInterstitialAd()
}
}
}
In viewDidLoad of GameViewController register for a notification, and later from the GameScene post a notification when you want the ad to appear.
so your viewDidLoad will have the following extra line
NSNotificationCenter.defaultCenter().addObserver(self, selector: "loadFBInterstitialAd", name: "loadAd", object: nil)
then write a method in Gamescene
func showAdNow() {
NSNotificationCenter.defaultCenter().postNotificationName("loadAd", object: nil)
}
now in Gamescene.swift replace the line
GameViewController().loadFBInterstitialAd()
with
showAdNow()
You try:
//GameViewController.swift
class GameViewController: UIViewController, FBInterstitialAdDelegate {
let interstitialFBAD: FBInterstitialAd = FBInterstitialAd(placementID: "65543456456456_454345345454534")
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as! SKView
skView.multipleTouchEnabled = false
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
scene.view?.userInteractionEnabled = true
skView.presentScene(scene)
scene.gvcDelegate = self
}
//GameScene.swift
class GameScene: SKScene {
gvcDelegate: GameViewController?
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if node.name == "retry" {
gvcDelegate.loadFBInterstitialAd()
}
}
}
Goodluck!

Issues with NSNotificationCenter in #IBAction function

I am working on an app that requires my main view controller to receive notifications from its child view controller. To do this, I set up the observer in the viewDidLoad() method of the parent controller, and I am trying to call the postNotificationName() function when a button is pressed that is located in the child view controller.
When the postNotificationName() call is located in the #IBAction func buttonPressed(){ } function, the observer never gets the notification. However, when the same code is called from a different function in the same view controller, it works.
I thought this might be a thread issue, and unsuccessfully tried many of the solutions for that issue. I'm not very familiar with threading, though, so maybe I still missed it. Does anyone have any idea what the issue might be?
Thanks for the help!
ViewController
class GameController: UIViewController {
override func viewDidLoad() {
super.init()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "attemptHumanMove:", name: Constants.NSNotificationKey.tilePressed, object: nil)
}
func attemptHumanMove(notification: NSNotification) {
print("test")
}
ChildViewController
#IBAction func tileTouched(sender: AnyObject) {
NSNotificationCenter.defaultCenter().postNotificationName(Constants.NSNotificationKey.tilePressed, object: nil, userInfo: ["a": 0])
}
Experimenting with the flow you have mentioned, the following code does receive the notification message from a child view controller.
ParentViewController
class ViewController: UIViewController {
#IBOutlet weak var notificationMsgLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
notificationMsgLabel.text = "Waiting for notification..."
NSNotificationCenter.defaultCenter().addObserver(self, selector: "attemptHumanMove:", name: "tilePressed", object: nil)
}
func attemptHumanMove(notification: NSNotification) {
print("Notification message received!")
notificationMsgLabel.text = "Notification received!!!"
}
}
ChildViewController
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sendNotification() {
print("Sending notification message!!!")
NSNotificationCenter.defaultCenter().postNotificationName("tilePressed", object: nil, userInfo: ["a": 0])
}
}
Here you can find the screen shot of the storyboard:
Storyboard Snapshot

Pass data via segue between 2 view controllers and update labels

I am trying to pass var projectNumber from ViewController to Project1ViewController via segue and save it as var projectNum. Then use projectNum to update the labels in Project1ViewController. The segue and action/outlets are all set up. The app runs fluently (no errors), however, projectNum in Project1ViewController is not getting the projectNumber value and making it projectNum.
How do I pass the projectNumber value from ViewController to Project1ViewController and save it in projectNum? I've seen tutorials that describe similar actions being performed via delegates, but I'm unsure if delegates are applicable to my question. Any feedback helps.
ViewController
import UIKit
class ViewController: UIViewController{
var projectNumber:String = ""
#IBOutlet var projectButton1 : UIButton!
#IBOutlet var projectButton2 : UIButton!
#IBOutlet var projectButton3 : UIButton!
#IBOutlet var projectButton4 : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func updateLabels(sender: UIButton!) {
projectNumber = String(sender.tag)
println(projectNumber)
sender.setTitle(String(projectNumber), forState: UIControlState.Normal)
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
//if user presses Project 3921 button
if segue.identifier == "Project3921Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//if user presses Project 3922 button
else if segue.identifier == "Project3922Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//if user presses Project 3923 button
else if segue.identifier == "Project3923Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//otherwise user presses Project 3924 button
else if segue.identifier == "Project3924Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
}
}
}
Project1ViewController
import UIKit
class Project1ViewController: UIViewController {
var projectNum:String!
#IBOutlet var projectNumLabel: UILabel!
#IBOutlet var projectNumTitle: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
projectNumLabel.text = projectNum
projectNumTitle.title = projectNum
println(projectNum)
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thanks!
You are defining prepareForSegueinside the button action function. It is a ViewController function to be overridden.
Your solution can be way more simpler:
class ViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = segue.identifier
}
}
}
Note you do not need the button outlets, since you just configure them in the storyboard with the proper segue identifier. Unless you need some other custom action to be triggered by the buttons.
And:
class Project1ViewController: UIViewController {
var projectNum:String!
#IBOutlet var projectNumLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
projectNumLabel.text = projectNum
self.title = projectNum
println(projectNum)
}
}
Note I just set the title property of Project1ViewController in order to present the projectNum as the title in the navigation controller. I assume your controllers are embedded in a navigation controller and the ViewController's buttons has show segues to Project1ViewController.

Simple mouseover effect on NSButton

I am creating a custom NSButtonCell for a custom rendering.
Now, I want to have different aspect depending if the mouse is over the button or not. How can I get this information?
Thanks and regards,
Here is i have created and worked for me perfectly...
Step 1: Create the Button with tracking area
NSButton *myButton = [[NSButton alloc] initWithFrame:NSMakeRect(100, 7, 100, 50)];
[myButton setTitle:#"sample"];
[self.window.contentView addSubview:myButton];
// Insert code here to initialize your application
NSTrackingArea* trackingArea = [[NSTrackingArea alloc]
initWithRect:[myButton bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
owner:self userInfo:nil];
[myButton addTrackingArea:trackingArea];
Step: 2 Implement the following methods
- (void)mouseEntered:(NSEvent *)theEvent{
NSLog(#"entered");
[[myButton cell] setBackgroundColor:[NSColor blueColor]];
}
- (void)mouseExited:(NSEvent *)theEvent{
[[myButton cell] setBackgroundColor:[NSColor redColor]];
NSLog(#"exited");
}
Swift 3:
Create the button with code or just use it's #IBOutlet.
Then define the button's tracking area for mouse over (hover):
let area = NSTrackingArea.init(rect: yourButtonName.bounds,
options: [.mouseEnteredAndExited, .activeAlways],
owner: self,
userInfo: nil)
yourButtonName.addTrackingArea(area)
Then override mouseEntered and mouseExited, set whatever you want to change (button color, button image, button text,..) in these functions:
override func mouseEntered(with event: NSEvent) {
print("Entered: \(event)")
}
override func mouseExited(with event: NSEvent) {
print("Exited: \(event)")
}
If you have multiple buttons (with tracking area added for each) and you need to identify which button triggered the mouseEntered event, you can add some userInfo information for this purpose, so instead of:
userInfo: nil
Add your custom button name in userInfo for each button, for example:
userInfo: ["btnName": "yourButtonName"]
Then you can write a switch-case or if statements in your mouseEntered and mouseExited functions like this:
override func mouseEntered(with event: NSEvent) {
// Identify which button triggered the mouseEntered event
if let buttonName = event.trackingArea?.userInfo?.values.first as? String {
switch (buttonName) {
case "yourButtonName":
//do whatever you want for this button..
case "anotherButtonName":
//do whatever you want for this button..
default:
print("The given button name: \"\(buttonName)\" is unknown!")
}
}
}
You need to Subclass the NSButton class (or even better the NSButtonCell class).
As Justin said if you put the two method
- (void)mouseEntered:(NSEvent *)theEvent;
- (void)mouseExited:(NSEvent *)theEvent;
They should get called when the mouse enter and exit the area. You may also need to re create the tracking area, look here:
- (void)updateTrackingAreas
For fade in and fade out effect I played with animator and alpha value for example:
[self animator]setAlphaValue:0.5];
Swift 5 version with callback, super easy to use:
final class HoverButton: NSButton {
private let callback: (HoverButton, Bool) -> Void
init(callback: #escaping (HoverButton, Bool) -> Void) {
self.callback = callback
super.init(frame: .zero)
let area = NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .activeAlways, .inVisibleRect], owner: self, userInfo: nil)
addTrackingArea(area)
}
#available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func mouseEntered(with event: NSEvent) {
super.mouseEntered(with: event)
callback(self, true)
}
override func mouseExited(with event: NSEvent) {
super.mouseExited(with: event)
callback(self, false)
}
}
Usage:
let button = HoverButton { button, isHovered in
button.animator().alphaValue = isHovered ? 1 : 0.5
}
a good starting point, declared in NSResponder:
- (void)mouseEntered:(NSEvent *)theEvent;
- (void)mouseExited:(NSEvent *)theEvent;
specifically, the button cell's container (not the cell itself) is the NSResponder.
For those who prefer subclassing, you can also make your own NSButton and assigning the NSTrackingArea in it.
Here is a really simple and elegant way to do it, thanks to Joey Zhou : https://github.com/Swift-Kit/JZHoverNSButton
It is written in Swift 2 but XCode will automatically translate it in Swift 3 - 4 without any issue.
Hope it can help someone
This is a simple code to track mouse enter and mouse exit events on some controls (Images, Label, etc...):
#IBOutlet weak var myImage: NSImageView!
#IBOutlet weak var myLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
let area1 = myTrakingArea(control: self.myImage)
let area2 = myTrakingArea(control: self.myLabel)
self.myImage.addTrackingArea(area1)
self.myLabel.addTrackingArea(area2)
}
func myTrakingArea(control: NSControl) -> NSTrackingArea {
return NSTrackingArea.init(rect: control.bounds,
options: [.mouseEnteredAndExited, .activeAlways],
owner: control,
userInfo: nil)
}
override func mouseEntered(with event: NSEvent) {
if let owner = event.trackingArea?.owner as? NSControl {
let id : String = owner.identifier!.rawValue
switch id {
case self.myLabel.identifier!.rawValue:
print("Entered Quit Label")
case self.myImage.identifier!.rawValue:
print("Entered Quit Image")
default:
print("Entered ???")
}
}
}
override func mouseExited(with event: NSEvent) {
if let owner = event.trackingArea?.owner as? NSControl {
let id : String = owner.identifier!.rawValue
switch id {
case self.myLabel.identifier!.rawValue:
print("Exited Quit Label")
case self.myImage.identifier!.rawValue:
print("Exited Quit Image")
default:
print("Exited ???")
}
}
}

Resources