使用 Swift 的带有建议标记的 NSTokenField
NSTokenField with suggested tokens using Swift
我是 Swift 的新手,来自 AppleScript Obj-C。我已经阅读了几本书,并且对语法感到满意,但我仍然感到很迷茫。
我正在尝试创建一个简单的令牌字段,它会建议自动完成令牌,就像 Apple Mail 在识别您的联系人中的电子邮件时所做的那样。我的灵感来自于this ASOC script (post #6)。我尽量在 swift 中复制它(没有标记上的操作菜单):
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var tokenField: NSTokenField!
var theNames = [String]()
func applicationDidFinishLaunching(aNotification: NSNotification) {
tokenField.setDelegate(tokenField.delegate())
theNames = ["Pomona", "Potomac", "Potable", "Process", "Plow"]
}
func tokenField(tokenField : NSTokenField, completionsForSubstring substring : String, indexOfSelectedItem selectedIndex : UnsafeMutablePointer<Int>) -> [AnyObject]? {
var thePredicate = NSPredicate(format: "SELF beginswith[cd] %@", substring)
var matchingNames = (theNames as NSArray).filteredArrayUsingPredicate(thePredicate)
return matchingNames as Array
}
func tokenField(tokenField : NSTokenField, hasMenuForRepresentedObject representedObject : AnyObject) -> Bool {
return true
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
所以总结一下。当用户键入时,如果第一个字母是 "p",则应弹出包含 "Pomona"、"Potomac"、"Potable"、"Process"、"Plow" 的菜单在单词下方。我不确定为什么什么都没有弹出。
有什么想法吗?
编辑:
2016 年 2 月 13 日
下面的 ioquatix 提供了我的问题的答案,但它超出了我目前的知识水平。他确实指出了我原始代码中的一个关键缺陷是缺少 NSTokenFieldCellDelegate
和 NSTokenFieldDelegate
。感谢他的帮助,我的(简单但有限的)解决方案是:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSTokenFieldCellDelegate, NSTokenFieldDelegate {
var names = ["Pat", "Pot"]
@IBOutlet weak var tokenField: NSTokenField!
func tokenField(tokenField: NSTokenField, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject]? {
return (names as NSArray).filteredArrayUsingPredicate(NSPredicate(format: "SELF beginswith[cd] %@", substring))
}
}
我已经使用 NSTokenFieldDelegate 方法实现了自动完成:
import Cocoa
import CoreData
class PMTagCompletionController : NSObject, NSTokenFieldDelegate, NSTokenFieldCellDelegate {
var managedObjectContext : NSManagedObjectContext?
var tagEntityName = "Tag"
func completionsForSubstring(substring : String) -> [String] {
if let managedObjectContext = self.managedObjectContext {
let tagEntity: NSEntityDescription? = NSEntityDescription.entityForName(self.tagEntityName, inManagedObjectContext: managedObjectContext)
let request: NSFetchRequest = NSFetchRequest.init()
request.entity = tagEntity;
if let allTags = try! managedObjectContext.executeFetchRequest(request) as? [PMTag] {
var tagNames : [String] = []
let lowercaseSubstring: String = substring.lowercaseString
for tag: PMTag in allTags {
if tag.name.lowercaseString.hasPrefix(lowercaseSubstring) {
tagNames.append(tag.name)
}
}
return tagNames
}
}
return []
}
func tokenFieldCell(tokenFieldCell: NSTokenFieldCell, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject] {
return self.completionsForSubstring(substring)
}
func tokenField(tokenField: NSTokenField, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject]? {
return self.completionsForSubstring(substring)
}
}
它使用来自 CoreData 的 PMTag 实例,这些实例代表各个标签,因此用于标签字段中的自动完成。这应该足够接近你想要的东西。
我是 Swift 的新手,来自 AppleScript Obj-C。我已经阅读了几本书,并且对语法感到满意,但我仍然感到很迷茫。
我正在尝试创建一个简单的令牌字段,它会建议自动完成令牌,就像 Apple Mail 在识别您的联系人中的电子邮件时所做的那样。我的灵感来自于this ASOC script (post #6)。我尽量在 swift 中复制它(没有标记上的操作菜单):
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var tokenField: NSTokenField!
var theNames = [String]()
func applicationDidFinishLaunching(aNotification: NSNotification) {
tokenField.setDelegate(tokenField.delegate())
theNames = ["Pomona", "Potomac", "Potable", "Process", "Plow"]
}
func tokenField(tokenField : NSTokenField, completionsForSubstring substring : String, indexOfSelectedItem selectedIndex : UnsafeMutablePointer<Int>) -> [AnyObject]? {
var thePredicate = NSPredicate(format: "SELF beginswith[cd] %@", substring)
var matchingNames = (theNames as NSArray).filteredArrayUsingPredicate(thePredicate)
return matchingNames as Array
}
func tokenField(tokenField : NSTokenField, hasMenuForRepresentedObject representedObject : AnyObject) -> Bool {
return true
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
所以总结一下。当用户键入时,如果第一个字母是 "p",则应弹出包含 "Pomona"、"Potomac"、"Potable"、"Process"、"Plow" 的菜单在单词下方。我不确定为什么什么都没有弹出。
有什么想法吗?
编辑:
2016 年 2 月 13 日
下面的 ioquatix 提供了我的问题的答案,但它超出了我目前的知识水平。他确实指出了我原始代码中的一个关键缺陷是缺少 NSTokenFieldCellDelegate
和 NSTokenFieldDelegate
。感谢他的帮助,我的(简单但有限的)解决方案是:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSTokenFieldCellDelegate, NSTokenFieldDelegate {
var names = ["Pat", "Pot"]
@IBOutlet weak var tokenField: NSTokenField!
func tokenField(tokenField: NSTokenField, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject]? {
return (names as NSArray).filteredArrayUsingPredicate(NSPredicate(format: "SELF beginswith[cd] %@", substring))
}
}
我已经使用 NSTokenFieldDelegate 方法实现了自动完成:
import Cocoa
import CoreData
class PMTagCompletionController : NSObject, NSTokenFieldDelegate, NSTokenFieldCellDelegate {
var managedObjectContext : NSManagedObjectContext?
var tagEntityName = "Tag"
func completionsForSubstring(substring : String) -> [String] {
if let managedObjectContext = self.managedObjectContext {
let tagEntity: NSEntityDescription? = NSEntityDescription.entityForName(self.tagEntityName, inManagedObjectContext: managedObjectContext)
let request: NSFetchRequest = NSFetchRequest.init()
request.entity = tagEntity;
if let allTags = try! managedObjectContext.executeFetchRequest(request) as? [PMTag] {
var tagNames : [String] = []
let lowercaseSubstring: String = substring.lowercaseString
for tag: PMTag in allTags {
if tag.name.lowercaseString.hasPrefix(lowercaseSubstring) {
tagNames.append(tag.name)
}
}
return tagNames
}
}
return []
}
func tokenFieldCell(tokenFieldCell: NSTokenFieldCell, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject] {
return self.completionsForSubstring(substring)
}
func tokenField(tokenField: NSTokenField, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer<Int>) -> [AnyObject]? {
return self.completionsForSubstring(substring)
}
}
它使用来自 CoreData 的 PMTag 实例,这些实例代表各个标签,因此用于标签字段中的自动完成。这应该足够接近你想要的东西。