04. Form表单相关(一) - NSLabel 标签和 NSTextField 文本输入控件

从本章开始会用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)
        
    }
相关推荐
lzhdim17 分钟前
iPhone 17 Air看点汇总:薄至6mm 刷新苹果轻薄纪录
ios·iphone
安和昂20 分钟前
【iOS】知乎日报第四周总结
ios
yngsqq3 小时前
037集——JoinEntities连接多段线polyline和圆弧arc(CAD—C#二次开发入门)
开发语言·c#·swift
麦田里的守望者江3 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin
Cod_Next4 小时前
Mac系统下配置 Tomcat 运行环境
java·macos·tomcat
_黎明4 小时前
【Swift】字符串和字符
开发语言·ios·swift
ZVAyIVqt0UFji6 小时前
iOS屏幕共享技术实践
macos·ios·objective-c·cocoa
hfxns_7 小时前
iOS 18.2 Beta 4开发者预览版发布,相机新增辅助功能
ios
Zhijun.li@Studio9 小时前
Mac下的vscode远程ssh免密码登录
vscode·macos·ssh
SoraLuna9 小时前
「Mac玩转仓颉内测版25」基础篇5 - 布尔类型详解
开发语言·算法·macos·cangjie