如何从 swift 中的 NSObject 访问元素?

How to access elements from an NSObject in swift?

我已经将一些变量设置为对象

import UIKit
class SpeedTestResult: NSObject {
    var testTime: NSDate?
}

然后在控制器中我设置这个对象并将它传递给一个class来存储它:

testResult.testTime = NSDate()
SpeedTestManager().addTestResult(testResult)

我需要存储这个对象,然后在视图中访问其中的元素,这就是我所拥有的:

import Foundation
class SpeedTestManager : NSObject {
    var testResultArray = [NSObject]()
    func addTestResult(testResult: NSObject) {
        testResultArray.append(testResult)
        print("Printing testResultArray: \(testResultArray)")

    }
}

但是当我尝试打印对象时,我得到了

Printing testResultArray: [<ProjectName.SpeedTestResult: 0x127b85e50>]

如何访问对象中的元素并存储此对象并检索它以供以后在视图中使用?

这是一种方法:

    import Foundation

    class SpeedTestResult: NSObject {
        var testTime: NSDate?
    }

    class SpeedTestManager : NSObject {
        var testResultArray = [NSObject]()
        func addTestResult(testResult: NSObject) {
            testResultArray.append(testResult)
            for result in testResultArray {
//  This will crash if result is not a SpeedTestResult.
//                print((result as! SpeedTestResult).testTime)
//  This is better:
               if let timeResult = result as? SpeedTestResult
               {
                   print(timeResult.testTime)
               }
               else 
               {
                   print("Not time type...")
               }
            }           
        }
    }

    var testResult = SpeedTestResult()
    testResult.testTime = NSDate()
    SpeedTestManager().addTestResult(testResult)

这解决了您的具体问题,但这里还有一些其他问题:

  • 如果您只打算将 SpeedTestResult 个实例存储在 testResultArray,那为什么不做成type呢 [SpeedTestResutl]()?
  • 如果你将不同类型的测试存储在数组中,那么如何 您找出 NSObject 元素代表哪种类型的测试? 有一些方法......在上面的代码中,我们至少确保我们没有将错误类型的对象视为 SpeedTestResult.
  • 当你做 SpeedTestManager().addTestResult(testResult) 时,你不会 保留对 SpeedTestManager 实例的引用。下一次 你打同样的电话,你会创建一个不同的 SpeedTestManager 实例。

  • 这不是真正的问题,但 SpeedTestManager 不必 是 NSObject 的子 class,除非你想在 Objective-C.

  • 您可能不想在中打印 testResultArray 的内容 addTestResult() 方法。你可以有其他方法 访问数组。

要将您的测试结果添加到同一个测试管理器,您可以这样做:

let myTestManager = SpeedTestManager()
myTestManager.addTestResult(testResult)     
// create other test results and add them ...
class TestResult : NSObject, NSSecureCoding {
    var testTime: NSDate?

    override init() {
        super.init()
    }

    @objc required init?(coder decoder: NSCoder) {
        self.testTime = decoder.decodeObjectForKey("testTime") as? NSDate
    }

    @objc func encodeWithCoder(encoder: NSCoder) {
        encoder.encodeObject(self.testTime, forKey: "testTime")
    }

    @objc static func supportsSecureCoding() -> Bool {
        return true
    }

    override var description: String {
        return String.init(format: "TestResult: %@", self.testTime ?? "null")
    }
}

class SpeedTestManager : NSObject, NSSecureCoding {
    var testResultArray = [NSObject]()

    func addTestResult(testResult: NSObject) {
        testResultArray.append(testResult)
        print("Printing testResultArray: \(testResultArray)")
    }

    override init() {
        super.init()
    }

    @objc func encodeWithCoder(encoder: NSCoder) {
        encoder.encodeObject(self.testResultArray, forKey: "testResultArray")
    }

    @objc required init?(coder decoder: NSCoder) {
        self.testResultArray = decoder.decodeObjectForKey("testResultArray") as! [NSObject]
    }

    @objc static func supportsSecureCoding() -> Bool {
        return true
    }

    override var description: String {
        return String.init(format: "SpeedManager: [%@]", self.testResultArray.map({"\([=10=])"}).joinWithSeparator(","))
    }
}

class TestViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()


        let testResult = TestResult()
            testResult.testTime = NSDate()

        let speedManager = SpeedTestManager()
            speedManager.addTestResult(testResult)

        NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(speedManager), forKey: "speedManager")
        NSUserDefaults.standardUserDefaults().synchronize()

        if let archivedSpeedManager = NSUserDefaults.standardUserDefaults().objectForKey("speedManager") as? NSData {
            let unarchivedSpeedManager = NSKeyedUnarchiver.unarchiveObjectWithData(archivedSpeedManager)
            print("SpeedManager: \(unarchivedSpeedManager ?? "null")")
        }
        else {
            print("Failed to unarchive speed manager")
        }
    }
}