2015-11-29 31 views
1

我是Swift新手,來自AppleScript Obj-C。我已經閱讀了幾本書,並且習慣了這種語法,但我仍然覺得很失落。帶有使用Swift的建議令牌的NSTokenField

我試圖創建一個簡單的令牌字段,它建議像Apple Mail一樣的自動完成令牌在識別聯繫人中的電子郵件時執行。我的靈感來自this ASOC script (post #6)。我試圖複製其在疾如盡我所能(不含上記號的操作菜單):

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」,「Plough」的菜單。我不知道爲什麼沒有彈出。

任何想法?


編輯:

2016年2月13日

下面ioquatix提供的回答我的問題,但它是超出了我目前的知識水平。他確實指出了我原來的代碼中的一個關鍵缺陷是缺少NSTokenFieldCellDelegateNSTokenFieldDelegate。多虧了他的幫助,我的(簡單但有限)的解決方案是:

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實例:

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)) 
    } 

} 

回答

1

我已經使用NSTokenFieldDelegate方法來實現自動完成因此被用於在標籤字段中自動完成。這應該足夠接近你想要工作的東西。

+0

謝謝你的回答。我對任何類型的編碼都很缺乏經驗,所以我擔心你的解決方案超出了我目前的理解範圍。但是,您在第一次嘗試時確實指出了一個明顯的缺陷。我未能添加'NSTokenFieldDelegate'和'NSTokenFieldCellDelegate'。當時我不明白代表是什麼人。 – user3803526

+0

你基本上可以用你已有的東西替換函數的主體,我只是包含了一個更「完整」的例子。 – ioquatix

+0

是的,我相信你的例子是一個更好的解決方案。我不知道發生了什麼,但是我很困惑'PMTag'。它是否在'NSManagedObjectContext'實例('managedObjectContext')中? – user3803526