简体   繁体   中英

How to access elements from an NSObject in swift?

I've set some variables as an Object

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

Then in the controller I set this object and pass it to a class to store it:

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

I need to store this object and then access the elements within in a view later, This is what I have:

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

    }
}

But when I try to print the the object I just get

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

How do I access elements within the object and store this object and retrieve it for later use in a view?

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({"\($0)"}).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")
        }
    }
}

Here is one way you can do it:

    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)

This addresses your specific question, but there are some other problems here:

  • If you are going to store only SpeedTestResult instances in testResultArray , then why not make it of type [SpeedTestResutl]() ?
  • If you will store different types of tests in the array, then how do you find out which type of test an NSObject element represents? There are ways... In the above code we at least make sure we are not treating a wrong type of object as a SpeedTestResult .
  • When you do SpeedTestManager().addTestResult(testResult) , you don't keep a reference to the SpeedTestManager instance. The next time you make the same call, you will be creating a different SpeedTestManager instance.

  • This is not really a problem, but SpeedTestManager does not have to be a sub-class of NSObject , unless you want to use it in Objective-C.

  • You probably don't want to print the content of testResultArray in the addTestResult() method. You could have other methods for accessing the array.

To add your test results to the same test manager, you could do:

let myTestManager = SpeedTestManager()
myTestManager.addTestResult(testResult)     
// create other test results and add them ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM