Keypad not showing on ios8 - ios8

It was performed as follows.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[view addSubView:nameTextField];
[nameTextField becomeFirstResponder];`
But the keypad does not appear.
After you press the Home key, and if you come back to the application, the keypad appears.
I do not know the cause.

check with Below code :
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillAppear:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillDisappear:", name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillAppear(notification: NSNotification){
// Do something here
}
func keyboardWillDisappear(notification: NSNotification){
// Do something here
}
and don't forget to remove observer in viewwillappear like below :
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}

Related

Mouse events (NSTrackingArea) in Playground not working

I have a a subclass of NSView which contains the following NSTrackingArea code. But for some reason the mouse events won't trigger in Playground.
The viewWillMoveToWindowis being called, but nothing else seems to fire. Does anyone have a clue to what is missing?
class MyView: NSView {
private var trackingArea: NSTrackingArea = NSTrackingArea()
// Other stuff omitted here...
// ...
override func viewWillMoveToWindow(newWindow: NSWindow?) {
// Setup a new tracking area when the view is added to the window.
trackingArea = NSTrackingArea(rect: self.bounds, options: [.MouseEnteredAndExited, .ActiveAlways], owner: self, userInfo: nil)
self.addTrackingArea(trackingArea)
}
override func updateTrackingAreas() {
self.removeTrackingArea(trackingArea)
trackingArea = NSTrackingArea(rect: self.bounds, options: [.MouseEnteredAndExited, .ActiveAlways], owner: self, userInfo: nil)
self.addTrackingArea(trackingArea)
}
// Mouse events
override func mouseEntered(theEvent: NSEvent) {
NSLog("MouseEntered")
}
override func mouseExited(theEvent: NSEvent) {
NSLog("MouseExited")
}
override func mouseDown(theEvent: NSEvent) {
NSLog("MouseDown")
}
}
According to this 2014 WWDC session:
There are few more limitations with Playgrounds.
Playgrounds cannot be used for things which require user interaction.
So we have great support for showing live views but you can only see them, you can't touch them.
You can find the original video here

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

NSTableView: detecting a mouse click together with the row and column

I'm trying to detect when a mouse click occurs in an NSTableView, and when it does, to determine the row and column of the cell that was clicked.
So far I've tried to use NSTableViewSelectionDidChangeNotification, but there are two problems:
It only triggers when the selection changes, whereas I want every mouse click, even if it is on the currently selected row.
The clickedRow and clickedColumn properties of NSTableView are both -1 when my delegate is called.
Is there a better (and correct) way of doing this?
There is a simple way.
Tested with Swift 3.0.2 on macOS 10.12.2 and Xcode 8.2.1
Let
tableView.action = #selector(onItemClicked)
Then
#objc private func onItemClicked() {
print("row \(tableView.clickedRow), col \(tableView.clickedColumn) clicked")
}
To catch the user clicking a row (only, when the user clicks a row, not when it is selected programmatically) :
Subclass your NSTableView and declare a protocol
MyTableView.h
#protocol ExtendedTableViewDelegate <NSObject>
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row;
#end
#interface MyTableView : NSTableView
#property (nonatomic, weak) id<ExtendedTableViewDelegate> extendedDelegate;
#end
MyTableView.m
Handle the mouse down event (note, the delegate callback is not called when the user clicks outside, maybe you want to handle that too, in that case, just comment out the condition "if (clickedRow != -1)")
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint globalLocation = [theEvent locationInWindow];
NSPoint localLocation = [self convertPoint:globalLocation fromView:nil];
NSInteger clickedRow = [self rowAtPoint:localLocation];
[super mouseDown:theEvent];
if (clickedRow != -1) {
[self.extendedDelegate tableView:self didClickedRow:clickedRow];
}
}
Make your WC, VC conform to ExtendedTableViewDelegate.
#interface MyViewController : DocumentBaseViewController<ExtendedTableViewDelegate, NSTableViewDelegate, NSTableViewDataSource>
set the extendedDelegate of the MyTableView to your WC, VC (MyViewController)
somewhere in MyTableView.m
self.myTableView.extendedDelegate = self
Implement the callback in delegate (MyViewController.m)
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
// have fun
}
I would prefer doing as follows.
Override
-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
Provide super implementation;
RequiredRow = row;
RequiredColumn = [tableView clickedColumn];
Hope this helps.
If someone is looking for a Swift 3/4/5 version of Peter Lapisu's answer:
Add an extension for the NSTableView (NSTableView+Clickable.swift):
import Foundation
import Cocoa
extension NSTableView {
open override func mouseDown(with event: NSEvent) {
let globalLocation = event.locationInWindow
let localLocation = self.convert(globalLocation, from: nil)
let clickedRow = self.row(at: localLocation)
super.mouseDown(with: event)
if (clickedRow != -1) {
(self.delegate as? NSTableViewClickableDelegate)?.tableView(self, didClickRow: clickedRow)
}
}
}
protocol NSTableViewClickableDelegate: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, didClickRow row: Int)
}
Then to use it, make sure you implement the new delegate protocol:
extension MyViewController: NSTableViewClickableDelegate {
#nonobjc func tableView(_ tableView: NSTableView, didClickRow row: Int) {
Swift.print("Clicked row \(row)")
}
}
The #nonobjc attribute silences the warning about it being close to didClick.
Just in case someone was looking for it in SWIFT and / or for NSOutlineView.
Based on #Peter Lapisu instructions.
class MYOutlineViewDelegate: NSOutlineView, NSOutlineViewDelegate,NSOutlineViewDataSource{
//....
}
extension MYOutlineViewDelegate{
func outlineView(outlineView: NSOutlineView, didClickTableRow item: AnyObject?) {
//Click stuff
}
override func mouseDown(theEvent: NSEvent) {
let globalLocation:NSPoint = theEvent.locationInWindow
let localLocation:NSPoint = self.convertPoint(globalLocation, fromView: nil)
let clickedRow:Int = self.rowAtPoint(localLocation)
super.mouseDown(theEvent)
if (clickedRow != -1) {
self.outlineView(self, didClickTableRow: self.itemAtRow(clickedRow))
}
}}
see the tableViewSelectionIsChanging notification, here are the the comments from NSTableView.h
/*
Optional - Called when the selection is about to be changed, but note, tableViewSelectionIsChanging: is only called when mouse events are changing the selection and not keyboard events.
*/
I concede that this might not be the surest way to correlate your mouse clicks, but it is another area to investigate, seeing that you are interested in mouse clicks.

which method is called when selecting a cell in the NSTableView in Cocoa OS X?

I have a NSTableView , i want to get the value present in the cell. I am having only one column so , i just need the row number
i can use this [tableView selectedRow]- but where do i put this i want to put this in a method that gets called on selection of any of the rows.
-(void)tableViewSelectionDidChange:(NSNotification *)notification{
NSLog(#"%d",[tableViewController selectedRow]);
}
The above method also does not work i am getting the error
-[NSScrollView selectedRow]: unrecognized selector sent to instance 0x100438ef0]
i want something like the method available in the iPhone tableview-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
What is tableViewController object? Only NSTableView instances respond to selectedRow. You can get current table view (the one that sent the notification) from notification's object property:
Objective-C:
-(void)tableViewSelectionDidChange:(NSNotification *)notification{
NSLog(#"%d",[[notification object] selectedRow]);
}
Swift:
func tableViewSelectionDidChange(notification: NSNotification) {
let table = notification.object as! NSTableView
print(table.selectedRow);
}
my 2 cents for Xcode 10/swift 4.2
func tableViewSelectionDidChange(_ notification: Notification) {
guard let table = notification.object as? NSTableView else {
return
}
let row = table.selectedRow
print(row)
}
In Swift 5.4:
Just use tableView.action = #selector(YOUR_METHOD), then in your method, try to do something with tableView.selectedRow.
This would simply do the trick. Take a look at the demo below:
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
tableView.action = #selector(didSelectRow)
}
#objc private func didSelectRow() {
print("Selected row at \(tableView.selectedRow)")
}
But please be aware that if nothing is selected, or you clicked outside of a cell, then you'll get a tableView.selectedRow of -1. So you might wanna check if the index is out of range before you use it. :)
Swift 3 (from Eimantas' answer):
func tableViewSelectionDidChange(_ notification: NSNotification) {
let table = notification.object as! NSTableView
print(table.selectedRow);
}
You should addObserver Notification like this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(tableViewSelectionDidChangeNotification)
name:NSTableViewSelectionDidChangeNotification object:nil];
It will action when tableView selected row
good luck
full guide In Swift 5:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.didSelectRow(_:)), name: NSTableView.selectionDidChangeNotification, object: tableView)
}
#objc
func didSelectRow(_ noti: Notification){
guard let table = noti.object as? NSTableView else {
return
}
let row = table.selectedRow
print(row)
}
deinit {
NotificationCenter.default.removeObserver(self)
}

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