swift - 附加到类内部的数组实际上并不是附加到调用对象?
问题描述
我在 ViewController.swift 中实例化一个对象,然后调用该对象的一个方法,以便可以将值附加到它的一个成员。但是,当我尝试访问新附加的值时,我收到“索引超出范围错误”。更具体地说,我试图newProduct : Product
在products : [Product]
方法getAllProducts()
和populateProducts
. 不过,在我追加之后,client : ThreeDCartAPIClient
ViewController 中的初始调用对象实际上并没有保留来自内部类方法的任何信息。为什么是这样?
我已经尝试在类方法中几乎所有地方都使用“self”并从初始化程序调用方法,但我一直得到相同的结果。
// ViewController.swift
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController {
@IBOutlet weak var featuredButton1Image: UIImageView!
let head : HTTPHeaders = [
"SecureUrl" : "https://someURL.3dcartstores.com/",
"PrivateKey" : "99999999999999999999999999999999",
"Token" : "11111111111111111111111111111111",
"ContentType": "application/json"
]
let ENDPOINT_URL = "https://apirest.3dcart.com/3dCartWebAPI/v1/"
var client = ThreeDCartAPIClient()
override func viewDidLoad() {
super.viewDidLoad()
// Hide the navigation bar on main screen
viewWillAppear(true)
// Make API request and load content
loadInitialUI()
}
func loadInitialUI() {
client.getAllProducts(url: ENDPOINT_URL, header: head)
// ******* Here I get an "index out of range" *********** //
featuredButton1Image.image = client.products[0].mainImage
}
}
// ThreeDCartAPIClient.swift
import Foundation
import Alamofire
import SwiftyJSON
class ThreeDCartAPIClient {
var products : [Product]
init() {
products = [Product]()
}
func getAllProducts(url: String, header: [String : String]) {
Alamofire.request(url + "Products", method: .get, headers: header).responseJSON {
response in // Start of a closure inside of Alamofire method
if response.result.isSuccess {
// Force unwrap the result value
let jsonResponse = JSON(response.result.value!)
// Populate each product field now
self.populateProducts(json: jsonResponse)
} else {
print("Failure")
}
}
}
func populateProducts(json : JSON) {
for (_, product) in json {
let newProduct = Product()
newProduct.sku.setSKU(json: product["SKUInfo"])
newProduct.shortDescription = product["ShortDescription"].stringValue
newProduct.mainImageFile = product["MainImageFile"].stringValue
Alamofire.request("https://SomeURL.3dcartstores.com/"
+ newProduct.mainImageFile).responseData { (response) in
if response.error == nil {
if let data = response.data {
newProduct.mainImage = UIImage(data: data)!
}
}
}
products.append(newProduct)
}
}
}
解决方案
完成异步任务后,您将在 products 数组中获取数据。由于异步任务,您无法立即获取数据。您可以在任务完成时使用委派通知。在 ThreeDCartAPIClient.swift 文件中编写协议:
protocol JsonResponseProtocol: class {
func asyncTaskCompleted()
}
在 ThreeDCartAPIClient 类里面写:
weak var jsonResponseDelegate: JsonResponseProtocol?
完成所有数据填充后(在您的情况下,将其写在 populateProducts() 的 for 循环之外):
self.jsonResponseDelegate?.asyncTaskCompleted()
在声明 var client = ThreeDCartAPIClient() 之后在您的 viewController 中添加以下内容(在 viewDidLoad() 中):
client.jsonResponseDelegate = self
然后在你的 viewController.swift 中写下:
extension ViewController: JsonResponseProtocol{
func asyncTaskCompleted(){
// if data populated successfully you can access from here
}
}
为了更好地练习,您可以从 ThreeDCartAPIClient 类中的 asyncTaskCompleted() 中发送数据数组。
推荐阅读
- android - 我正在接收 json 对象,但改造将其视为数组?
- oauth - 使用 jhipster 将视频上传到 youtube?
- bash - Bash script: If any argument ($@) equals "foo" then… throws "too many arguments"
- javascript - 条纹 IBAN 元素错误“类型‘sepa_debit’不是有效的源类型。”
- jersey - Jersey 客户端发布 PUT InputStream“400 错误请求”
- php - PHP 通过在 x 个字符后的最后一个空格处截取字符串来摘录
- vb.net - 数组(或多维数组)中的单词组合
- java - 使用 DOCX4j 覆盖现有表行
- cloud - 为什么我的公共 IP 来自美国,而我的 VM 位于 southamerica-east1-a?
- postgresql - postgres 中的 sp_send_dbmail 替代方案?发送 Postgres 电子邮件报告的简单方法?