代码之家  ›  专栏  ›  技术社区  ›  theDC

如何在Swift中从Contentful访问图像?

  •  0
  • theDC  · 技术社区  · 8 年前

    以下是我获取条目的方式:

    func fetchAllEntriesByLocation(latitude:Double, longitude: Double, completion: @escaping (([Item]) ->Void)) {
        var items:[Item] = []
    
        let query = Query(where: "content_type", .equals("item")).where("fields.location", .isNear(Location(latitude: latitude, longitude: longitude)))
        client.fetchEntries(with: query) { [weak self] result in
            guard let strongSelf = self else { return }
            DispatchQueue.main.async {
                strongSelf.delegate?.finishedTask()
            }
            switch result {
            case .success(let entries):
                entries.items.forEach { entry in
                    items.append(Item(entry: entry))
                }
                DispatchQueue.main.async {
                    completion(items)
                }
            case .error(let error):
                print(error)
            }
        }
    
    }
    

    以及我如何绘制它们

    final class Item: EntryModellable {
    
    static let contentTypeId: String = "item"
    
    let name: String
    let location: Location
    let address: String
    let open: String
    let desc: String
    let phone: String
    let url: String
    let thumbUrl: Asset
    
    
    init(entry: Entry) {
        self.name = entry.fields["name"] as? String ?? ""
        self.location = entry.fields["location"] as? Location ?? Location(latitude: 52.23, longitude: 20.9)
        self.open = entry.fields["open"] as? String ?? ""
        self.address = entry.fields["address"] as? String ?? ""
        self.desc = entry.fields["opis"] as? String ?? ""
        self.phone = entry.fields["phone"] as? String ?? ""
        self.url = entry.fields["www"] as? String ?? ""
        self.thumbUrl = entry.fields["thumb"] as? Asset
    }
    

    }

    尝试映射到时出现问题 Asset 类型虽然当我打印条目时,我看到对于“thumb”键,变量的类型是 Contentful.Link.asset(Contentful.Asset) 。因此,我无法将其转换为资产类型。

    我想要实现的就是存储图像Url,以便稍后与翠鸟或类似的库一起使用它来加载图像。

    存储图像以访问其url的正确方法是什么?

    编辑:

    我尝试了下面提供的解决方案,现在出现以下运行时错误: enter image description here

    错误是:

    致命错误:在展开可选值时意外发现nil

    1 回复  |  直到 8 年前
        1
  •  5
  •   loudmouth    8 年前

    看起来您使用的是旧版本的SDK。知足的人。swift SDK现在位于 version 1.0.1 强烈建议升级到最新版本,该版本带来了API的稳定性,以及使用 EntryDecodable 协议它利用了Swift 4 Decodable 协议,因此您可以使用SDK提供的标准lib+一些助手扩展方法来控制JSON如何映射到您的类型!

    心满意足。swift 1.0.1 入口可解码 协议将正确链接所有类型和资产,而不会创建重复项。您的类如下所示(请注意,如果您有Contentful中不需要的属性(因此可以在响应中省略),那么应该使用 decodeIfPresent 返回一个可选的。

    final class Item: EntryDecodable, ResourceQueryable {
    
        static let contentTypeId: String = "item"
    
        let sys: Sys
        let name: String
        let location: Location
        let address: String
        let open: String
        let desc: String
        let phone: String
        let url: String
    
        // Links must be optional variables as they are resolved after the initializer exits        
        var thumbUrl: Asset? 
    
        public required init(from decoder: Decoder) throws {
            sys             = try decoder.sys()
            let fields      = try decoder.contentfulFieldsContainer(keyedBy: Item.Fields.self)
            name            = try fields.decode(String.self, forKey: .name)
            desc            = try fields.decode(String.self, forKey: .desc)
            location = try? fields.decodeIfPresent(Location.self, forKey: .location) ?? Location(latitude: 52.23, longitude: 20.9)
            address = try fields.decode(String.self, forKey: .address)
            open = try fields.decode(String.self, forKey: .open)
            phone  try fields.decode(String.self, forKey: .phone)
            url = try fields.decode(String.self, forKey: .url) 
    
    
            // Here is how you resolve your Asset.
            try fields.resolveLink(forKey: .thumbUrl, decoder: decoder) { [weak self] linkedAsset in
                self?.thumbUrl = linkedAsset as? Asset
            }
        }
    
        // If your Contentful field names differ from your property names, define the mapping here.
        enum Fields: String, CodingKey {
            case name, location, open, address, phone
            case url      = "www"
            case desc     = "opis"
            case thumbUrl = "thumb"
        }
    }
    

    现在,您需要更新查询:

    let query = QueryOn<Item>.where(field: .location, .isNear(Location(latitude: latitude, longitude: longitude)))
    client.fetchMappedEntries(matching: query) { [weak self] (result: Result<MappedArrayResponse<Item>>) in
        // Handle your data here, the thumbUrl field will contain a resolved asset for your entries (if that relationship exists in Contentful)
        switch result {
            case .success(let arrayResponse):
                if let firstItem = arrayResponse.items.first {
                    print(firstItem.thumburl?.urlString) 
                }
            case .error(let error):
                print(error)        
        }
    }