2014-10-31 34 views
2

我想存儲在AnyObject一個值,那麼在以後檢索如下:在斯威夫特,爲AnyObject,我怎麼SETVALUE(),然後調用valueForKey()

var obj:AnyObject = UIButton() 
obj.setValue("James", forKey: "owner") 
obj.valueForKey("owner") 

然而,AnyObject不允許它即使這些方法可用如錯誤所示:

setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key owner.' 

這怎麼可以做到?

+2

UIButton和AnyObject都沒有屬性'owner',所以你在這裏期待什麼? – matt 2014-10-31 04:14:05

+0

@matt,「owner」只是任何用戶定義的密鑰。主要問題是如何使用.setValue和。valueForKey方法是否可用(編譯)爲AnyObject? – yjsa 2014-11-01 13:40:44

+0

你正在使用它們就好。這就是爲什麼你的應用程序編譯。但是,當你的應用程序運行時,這是事實證明,沒有這樣的關鍵。正如我在下面的回答中所說的,對於UIButton或AnyObject沒有「用戶定義的鍵」。 – matt 2014-11-01 15:26:29

回答

5

你不能分配給一個UIButton的任意鍵。有些類允許這樣做(CALayer和CAAnimation想起來,當然還有NSDictionary),但是UIButton和AnyObject都不是這樣的類,它們都沒有屬性 - 所以試圖設置它是無稽之談,那就是導致運行時崩潰。你可以使用一個鍵來設置一個按鈕的現有的屬性,但是你不能像這樣發明自己的鍵。

+0

運行時對象關聯是否容易從Swift中獲取? – Tommy 2014-11-01 18:05:09

+0

@Tommy號在大多數語言中,它們很難得到,因爲對象的內存佈局是固定的。該功能很少需要,不過因爲它需要動態地訪問一個屬性(使用它的名字),並且有更簡單的方法來實現相同的功能,例如,封裝,繼承或單獨的字典。 Swift不是JavaScript。 – Sulthan 2014-11-01 18:23:59

+0

@Tommy你最近想做什麼?可能有一種更簡單的方法......在我看來,你問了一個錯誤的問題 - 你已經提出了一種實現你的目標的方式,而不是要求如何實現這個目標。 – matt 2014-11-01 19:49:39

1

關於您的按鈕,您可以創建可以存儲的對象數組。請參閱下面的NSCoding的使用。

類,我定義對象 - 例如從比賽中我寫道:

import Foundation 

class ButtonStates: NSObject { 

    var sign: String = "+" 
    var level: Int = 1 
    var problems: Int = 10 
    var time: Int = 30 
    var skipWrongAnswers = true 

    func encodeWithCoder(aCoder: NSCoder!) { 
     aCoder.encodeObject(sign, forKey: "sign") 
     aCoder.encodeInteger(level, forKey: "level") 
     aCoder.encodeInteger(problems, forKey: "problems") 
     aCoder.encodeInteger(time, forKey: "time") 
     aCoder.encodeBool(skipWrongAnswers, forKey: "skipWrongAnswers") 
    } 

    init(coder aDecoder: NSCoder!) { 
     sign = aDecoder.decodeObjectForKey("sign") as String 
     level = aDecoder.decodeIntegerForKey("level") 
     problems = aDecoder.decodeIntegerForKey("problems") 
     time = aDecoder.decodeIntegerForKey("time") 
     skipWrongAnswers = aDecoder.decodeBoolForKey("skipWrongAnswers") 
    } 

    override init() { 
    } 
} 

類,我歸檔和檢索這些對象:從視圖控制器獲取數據的

import Foundation 

class ArchiveButtonStates:NSObject { 

    var documentDirectories:NSArray = [] 
    var documentDirectory:String = "" 
    var path:String = "" 

    func ArchiveButtons(#buttonStates: ButtonStates) { 
     documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 
     documentDirectory = documentDirectories.objectAtIndex(0) as String 
     path = documentDirectory.stringByAppendingPathComponent("buttonStates.archive") 

     if NSKeyedArchiver.archiveRootObject(buttonStates, toFile: path) { 
      //println("Success writing to file!") 
     } else { 
      println("Unable to write to file!") 
     } 
    } 

    func RetrieveButtons() -> NSObject { 
     var dataToRetrieve = ButtonStates() 
     documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 
     documentDirectory = documentDirectories.objectAtIndex(0) as String 
     path = documentDirectory.stringByAppendingPathComponent("buttonStates.archive") 
     if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? ButtonStates { 
      dataToRetrieve = dataToRetrieve2 as ButtonStates 
     } 
     return(dataToRetrieve) 
    } 
} 

例如:

let buttonStates = ArchiveButtonStates().RetrieveButtons() as ButtonStates 

存儲來自ViewController的數據的示例:

ArchiveGameData().ArchiveResults(dataSet: gameDataArray) 
3

您不能僅僅動態地將屬性添加到對象。這不是Swift的工作原理。你可以在Javascript中使用它(而在Obj-C中使用它),但不能在Swift中使用它。

有幾種簡單的方法,你的問題:

  1. 封裝 - 創建一個類封裝一個按鈕,它的主人,例如OwnedButton
  2. 繼承 - 重寫UIButton,添加一個新的owner屬性。然後你就可以設置button.owner = ...
  3. 讓擁有者保存它擁有的按鈕owner.addButton(button)
  4. 單獨保存關係,例如,使用按鈕擁有者字典。
-1

UIButton,-[NSObject setValue:forKey:]-[NSObject valueForKey:]是Objective-C Cocoa API。所以,你的代碼不會對完全相同的工作,原因是相應的Objective-C代碼不起作用:

id obj = [[UIButton alloc] init]; 
[obj setValue:@"James" forKey:@"owner"]; 
[obj valueForKey:@"owner"]; 

一旦你明白這一點,你會想通的問題與您的代碼。