草庐IT

ios - Swift:尝试从数据源结构中检索数据

coder 2024-01-30 原文

下面是我的代码:

class DataSource: NSObject {
    var categories = [String]()
    var items = [Item]()

    private override init() {
        super.init()
    }

    class var sharedDataSource: DataSource {
        struct Static {
            static var onceToken: dispatch_once_t = 0
            static var instance: DataSource!
        }
        dispatch_once(&Static.onceToken) {
            let dataSource = DataSource()
            Static.instance = dataSource

            let urlPath = "myUrlPathString"
            let endpoint = NSURL(string: urlPath)
            let request = NSMutableURLRequest(URL: endpoint!)

            NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in
                let json = JSON(data: data!)
                print(json)
                for obj in json.arrayValue {
                    let item: Item = Item()
                    item.itemID = obj["item"].stringValue
                    item.price = obj["price"].floatValue
                    item.title = obj["title"].stringValue
                    item.category = obj["category"].stringValue
                    item.available = obj["available"].boolValue
                    item.image = obj["image"].stringValue
                    print(item.title)
                    dataSource.items.append(item)
                    print(dataSource.items)
                    print("STOP")
                }
            }).resume()
        }
        return Static.instance
    }
}

我试图通过将其结果分配给 Item 数组来在 UICollectionView 中使用此数据源的结果。我成功地获取了我的 NSURLSession 中的数据,并且正在填充其本地列表“items”。

在我的 UICollectionView 中,在我的 viewDidLoad 中,我按如下方式分配局部变量:

let dataSource = DataSource()
items = dataSource.sharedInstance.items

在 viewDidLoad 中打印值总是会产生一个没有值的空数组,但我知道在 NURLSession 完成时值已经存在。我不确定如何为此编写完成处理程序。这是我第一次使用作为结构的 sharedDataSource 做这种事情。

有什么想法吗?

谢谢,

肖恩

最佳答案

如果您在 viewDidLoad 中执行此操作,则可能在您尝试获取项目数组时 NSURL session 尚未完成。收到数据后,在您的数据源类中发送通知,然后设置项目。

例如

 NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in
            let json = JSON(data: data!)
            print(json)
            for obj in json.arrayValue {
                let item: Item = Item()
                item.itemID = obj["item"].stringValue
                item.price = obj["price"].floatValue
                item.title = obj["title"].stringValue
                item.category = obj["category"].stringValue
                item.available = obj["available"].boolValue
                item.image = obj["image"].stringValue
                print(item.title)
                dataSource.items.append(item)
                print(dataSource.items)
                print("STOP")
            }
            NSNotificationCenter.defaultCenter().postNotificationName("dataRecievedNotification", object: nil)

        }).resume()

但是您还需要能够在带有 collectionView 的 ViewController 中接收此通知。所以在viewDidLoad中添加

NSNotificationCenter.defaultCenter().addObserver(self, selector: "dataRecieved", name: "dataRecievedNotification", object: nil)

然后在同一个ViewController中添加一个函数:

func dataRecieved() {
    print("data received")
    items = dataSource.sharedInstance.items
    collectionView.reloadData()
}

其中dataSource是viewDidLoad上面声明的变量:

let dataSource = DataSource()

不要忘记,如果你正在使用观察者,你需要在类从内存中移除时移除它们,因此在 ViewController 中添加这个 deinit 函数:

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

编辑:我认为您的单例模式可以使用现代 swift 进行简化。您不必再使用 struct 或 dispatch_once ,只需声明一个 static let shared 实例即可为您处理所有这些。考虑到这一点,我尝试简化您的数据源类:

class DataSource {

static let sharedInstance = DataSource()

var items = [Item]()

private init() {}

func retrieveItems() {

    let urlPath = "myUrlPathString"
    let endpoint = NSURL(string: urlPath)
    let request = NSMutableURLRequest(URL: endpoint!)

    NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in

        let json = JSON(data: data!)
        print(json)

        for obj in json.arrayValue {
            let item: Item = Item()
            item.itemID = obj["item"].stringValue
            item.price = obj["price"].floatValue
            item.title = obj["title"].stringValue
            item.category = obj["category"].stringValue
            item.available = obj["available"].boolValue
            item.image = obj["image"].stringValue
            print(item.title)
            items.append(item)
            print(items)
            print("STOP")
        }

        NSNotificationCenter.defaultCenter().postNotificationName("dataRecievedNotification", object: nil)

    }).resume()

}

}

您在 viewDidLoad 中添加以下逻辑:

if DataSource.sharedInstance.items.count == 0 {
    DataSource.sharedInstance.retrieveItems()
}

然后将dataRecieved改成

func dataRecieved() {
    print("data received")
    items = DataSource.sharedInstance.items //Notice the capital
    collectionView.reloadData()
}

并删除 viewDidLoad 上面的 var dataSource = DataSource() 声明

关于ios - Swift:尝试从数据源结构中检索数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37013739/

有关ios - Swift:尝试从数据源结构中检索数据的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  6. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  7. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  8. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐