从本章开始会用3~4篇文章详细介绍下和Form表单相关的控件,本节主要介绍下NSLabel和NSTextField输入相关的几个控件。
文本输入框包含两类:NSTextField 和 NSSecureTextField,后者用于输入密码。基础控件的作用都差不太多,本节会以NSTextField为例做一个详细介绍,其它的几个控件的使用方法可参考NSTextField的描述。
NSTextField
先设计如下一个简单界面:
基础设置
在 attributes 面板中可设置很多内容,包括样式和一些其它的属性:
- title :默认文本
- placeholder:占位提示文本
- text color:文本颜色
- behavior:none-只读不支持选择, editable读写,selectable只能选择文本
- text direction:文本输入的方向
修改事件侦听
文本框的输入事件 是通过实现 NSTextFieldDelegate
协议的代理方法回调通知实现的,如果需要侦听则需要绑定各个输入框的Outlets到AppDelegate上面(设置代理,限XIB方式)。
然后就可以实现回调方法了,需要注意不同swift版本的实现不太一样:
修改Swift Language Version 的方法是在product-> target->Build settings -> swift Language version 中设置的。
swift
//以下代码是swift v4版本
class AppDelegate: NSObject, NSApplicationDelegate,NSTextFieldDelegate
@IBOutlet var window: NSWindow!
@IBOutlet weak var userName: NSTextField!
@IBOutlet weak var userPwd: NSSecureTextField!
override func controlTextDidBeginEditing(_ obj: Notification) {
if let textField = obj.object as? NSTextField {
//取值
let text = textField.stringValue
if(textField == self.userName){
print("userName:\(text)")
}
if(textField == self.userPwd){
print("password:\(text)")
}
}
}
override func controlTextDidChange(_ obj: Notification) {
if let textField = obj.object as? NSTextField {
let text = textField.stringValue
if(textField == self.userName){
print("userName:\(text)")
}
if(textField == self.userPwd){
print("password:\(text)")
}
}
}
文本内容获取
获取输入框的文本内容
swift
textField.stringValue
richTextField.attributedStringValue
拦截特殊按键
侦听特殊按键,在后面事件一节中会有详细讲解,此处会用即可,此功能也是 NSTextFieldDelegate
协议中的一个方法:
swift
// AppDelegate.swift
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if (commandSelector == #selector(NSResponder.insertNewline(_:))) {
// Press ENTER key
print("enter")
return true
} else if (commandSelector == #selector(NSResponder.deleteForward(_:))) {
// Press DELETE key
return true
} else if (commandSelector == #selector(NSResponder.deleteBackward(_:))) {
// Press BACKSPACE key
return true
} else if (commandSelector == #selector(NSResponder.insertTab(_:))) {
// Press TAB key
return true
} else if (commandSelector == #selector(NSResponder.cancelOperation(_:))) {
// Press ESC key
return true
}
return false
}
NSTextView
多行文本输入框,这东西是一个多层结构,最外层是NSScrollView,最内层才是NSTextView,所以绑定的时候不要弄错了。
基础设置
- Linguistics:智能化的一些设置,比如拼写检查等;
修改事件侦听
同样的,TextView的事件是通过实现 NSTextDelegate
协议的代理方法回调通知实现的,同样的要侦听的控件也需要绑定到AppDelegate对象上面(设置代理,限XIB方式)。
swift
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate, NSTextDelegate {
@IBOutlet var window: NSWindow!
@IBOutlet var textViewNS: NSTextView!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
func textDidBeginEditing(_ notification: Notification) {
if let textView = notification.object as? NSTextView {
let text = textView.string
print("textDidBeginEditing text \(text)")
}
}
func textDidEndEditing(_ notification: Notification) {
if let textView = notification.object as? NSTextView {
let text = textView.string
print("textDidEndEditing text \(text)")
}
}
func textDidChange(_ notification: Notification) {
if let textView = notification.object as? NSTextView {
let text = textView.string
print("textDidChange text \(text)")
}
}
}
文本内容获取
swift
textView.string
NSSearchField
实时检索
搜索文本框,可实现类似实时搜索的效果,实时效果需要绑定IBAction方法:
swift
@IBAction func searchTextFieldAction(_ sender: NSSearchField) {
let text = sender.stringValue
print("searchAction:\(text)")
}
修改事件侦听
除了上面的事件,输入文字后左右会分别显示放大镜和一个清除按钮,这两个按钮也可以添加事件侦听,放大镜相当于点击enter
时调用的事件,上述功能没有现成的Delegate,需要手工编码实现,实现代码如下:
注册事件侦听
swift
func applicationDidFinishLaunching(_ aNotification: Notification) {
self.registerSearchButtonAction()
}
实 现侦听事件
swift
//自行添加事件
func registerSearchButtonAction(){
//搜索按钮
let searchButtonCell = self.searchField.cell as! NSSearchFieldCell
let searchButtonActionCell = searchButtonCell.searchButtonCell!
searchButtonActionCell.target = self
searchButtonActionCell.action = #selector(searchButtonAction(_:))
//取消按钮
let cancelButtonCell = self.searchField.cell as! NSSearchFieldCell
let cancelButtonActionCell = cancelButtonCell.cancelButtonCell!
cancelButtonActionCell.target = self
cancelButtonActionCell.action = #selector(cancelButtonAction(_:))
}
@IBAction func searchButtonAction(_ sender: NSSearchField) {
print("点击了搜索按钮")
self.searchTextFieldAction(sender)
}
@IBAction func cancelButtonAction(_ sender: NSSearchField) {
print("文本内容已清除")
sender.stringValue = ""
}
NSLabel
本质上是NSTextField,只是官方事先进行了一些特殊的属性设置,目的是为了方便使用。
基础设置
- Layout:scrolls 单行显示, wraps多行显示
- Line Break:控制文本超出时的显示模式
编码实现简单标签
以下是完成时的样子
swift
func addLabel(){
let frame = CGRect(x: 20, y: 123, width: 222, height: 24)
let label = NSTextField(frame: frame)
label.isEditable = false
label.isBezeled = false
label.drawsBackground = false
label.stringValue = "我是代码添加的Label"
self.window.contentView?.addSubview(label)
}
编码实现超链接标签
URI点击跳转。
swift
func addRichableLabel(){
let text = NSString(string: "http://www.korg8.com/")
let attributedString = NSMutableAttributedString(string:text as String)
let linkURLText = "http://www.korg8.com/"
let linkURL = NSURL(string:linkURLText)
let selectedRange = text.range(of: linkURLText)
attributedString.beginEditing()
attributedString.addAttribute(NSAttributedStringKey.link, value:linkURL!, range: selectedRange)
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value:NSColor.blue, range: selectedRange)
attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value:NSUnderlineStyle.styleSingle.rawValue, range: selectedRange)
attributedString.endEditing()
let frame = CGRect(x: 20, y: 93, width: 222, height: 24)
let richTextLabel = NSTextField(frame: frame)
richTextLabel.isEditable = false
richTextLabel.isBezeled = false
richTextLabel.drawsBackground = false
richTextLabel.attributedStringValue = attributedString
self.window.contentView?.addSubview(richTextLabel)
}