关于ios:如何运行多个NSURLSessionDownloadTask \\,以便我可以从Instagram下载多个用户照片流?

How to run multiple NSURLSessionDownloadTask's so I can download multiple user photo streams from Instagram?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
//  ViewController.swift
//  Fashun
//
//  Created by Alex Macleod on 20/10/14.
//  Copyright (c) 2014 Alex Macleod. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

var collectionView: UICollectionView?

var instanceOfCustomObject: CustomObject = CustomObject()
var accessToken: NSString!
var userDefaults: NSUserDefaults!
let colorWheel = ColorWheel()
var photoCount: Int! = 0
let photos = NSMutableArray()

override func viewDidLoad() {
    super.viewDidLoad()

    userDefaults = NSUserDefaults.standardUserDefaults()
    self.accessToken = userDefaults!.objectForKey("accessToken") as NSString
    println(self.accessToken)

//        instanceOfCustomObject.someProperty ="Hello World"
//        var accessToken : NSString? = NSString(instanceOfCustomObject.accessToken)
//        println(accessToken)
//        instanceOfCustomObject.authorize()

// Do any additional setup after loading the view, typically from a nib.
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
//        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
    layout.itemSize = CGSize(width: 124, height: 124)
    layout.minimumInteritemSpacing = 1.0
    layout.minimumLineSpacing = 1.0
    collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    collectionView!.dataSource = self
    collectionView!.delegate = self
    collectionView!.registerClass(Cell.self, forCellWithReuseIdentifier:"Cell")
    collectionView!.backgroundColor = UIColor.whiteColor()
    self.view.addSubview(collectionView!)

    getData()
}

    func getData() -> Void {
        let baseUrl = NSURL(string:"https://api.instagram.com/v1/users/7522782/media/recent/?access_token=\\(self.accessToken)")

//        let forcastUrl = NSURL(string:"37.8267,-122.423", relativeToURL: baseUrl)

        //        let data = NSData(contentsOfURL: forcastUrl)
        //        println(data)
        let sharedSession = NSURLSession.sharedSession()
        let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(baseUrl!, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in


            //            var urlContents = NSString.stringWithContentsOfURL(location, encoding: NSUTF8StringEncoding, error: nil)
            //            println(urlContents)

            let dataObject = NSData(contentsOfURL: baseUrl!)

            if (error == nil) {
                let responseDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
//                println(responseDictionary)

                var currentResponse = responseDictionary.valueForKeyPath("data.images.standard_resolution.url") as NSArray



                dispatch_async(dispatch_get_main_queue(), { () -> Void in

//                    for url in currentResponse {
//                        var urlStrings: NSString = url as NSString
//                        
//                        var images =  UIImage(data: NSData(contentsOfURL: NSURL(string:urlStrings)!)!)
//
//                    }
                    for url in currentResponse {
                        var urls: NSString = url as NSString
                        //                        println(images)
                        var photoUrls = NSURL(string: urls)

                        var err: NSError?
                        var imageData :NSData = NSData(contentsOfURL: photoUrls!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)!
                        self.photos.addObject(UIImage(data:imageData)!)
                        println(self.photos)
                    }

                    self.photoCount = currentResponse.count as Int

                    self.collectionView?.reloadData()

                })

            } else {

                let networkIssueController = UIAlertController(title:"Error", message:"Something went wrong get a better phone you pleb!", preferredStyle: .ActionSheet)
                let okButton = UIAlertAction(title:"OK", style: .Default, handler: nil)
                networkIssueController.addAction(okButton)
                let cancelButton = UIAlertAction(title:"Cancel", style: .Cancel, handler: nil)
                networkIssueController.addAction(cancelButton)

                self.presentViewController(networkIssueController, animated: true, completion: nil)

                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    //Stop refresh animation


                })
            }
        })

        downloadTask.resume()

    }


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return photoCount

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as Cell
//                println(photos)
//            cell.textLabel.text ="Text"
    cell.imageView.image = photos.objectAtIndex(indexPath.row) as? UIImage
//    cell.photo = self.photos[indexPath.row] as? NSDictionary
    cell.imageView.backgroundColor = colorWheel.randomColor()

    return cell
}
}

您可以看到我有一个NSURLDownload会话,该会话从用户" 7522782"下载instagram信息。我解析数据并计算" currentResponse "数组以获取集合视图中所需的单元格数。然后,我将信息转换网址解析为UIimages并将其放入单元格中。

如何为一个以上的用户执行此操作。我想显示20位用户的照片。
请记住,我需要汇总所有用户的照片总数,以告诉我的收藏夹视图可以制作多少个单元格。

谢谢。


这是我现在想的一种方式...

首先修复您使用分派的方式...关于分派队列的好答案

1
2
//Might run into an issue that if you insert more heavy logic here your UI will get stuck until processing ends.
dispatch_async(dispatch_get_main_queue(), { () -> Void in }

因此,请改为使用dispatch_get_global_queue进行后台线程处理,然后在要运行将在后台闭包(块)内更新UI的代码时调用dispatch_get_main_queue。

1
2
3
4
5
6
7
8
9
10
//Correct way to use it to do Background work.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {

   //async code the callings to the NSUrlSession any other logic

       dispatch_async(dispatch_get_main_queue(), { () -> Void in
          //Do UI Updates Code.
       }

}

现在根据您的具体情况。您正在正确地处理该用户,获取该用户的"照片"的所有网址,因此现在添加类似这样的内容以处理同一屏幕上的多个用户。问题是下载20张用户照片需要花费很长时间,但是由于您执行的是异步操作,因此屏幕不会卡住。

对照片进行矩阵处理;主阵列中的每个阵列都是每个用户的照片集。

1
var photoUserMatrix = [NSMutableArray]() //using Swift array and NSMutableArray

或者使用它,因为您更倾向于NSMutableArrays

1
2
var photoUserMatrix = NSMutableArray()  
photoUserMatrix.addObject(NSMutableArray())//Each Photo Set per user is a new array.

矩阵的问题是发现执行时间为O(N ^ 2)。

现在无论如何您都可以拥有X个用户,并且您的代码可以处理它。通过使用这段代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Use this pseudo code to start downloading the multiple pictures for the users.
for i in 0...countOfUsers{

   //Create the array of Photos for this user.
   var newPhotoSet = NSMutableArray()

   //Now use your code that downloads the photos with
   //the Urls given for that users photos. with another loop on the Count of Urls/Photos
   for pos in 0...countOfUrls{

         //Download the Image with NSUrlSession

         //and add the photo to the new Array in the CompletionHandler
         newPhotoSet.AddObject(newImageDownloaded);
   }

   photoUserMatrix.addObject(newPhotoSet)


}

显示CollectionViewCells的代码。

1
2
3
4
5
6
7
8
9
10
11
for photoSet in photoUserMatrix as (NSMutableArray) {

    var count:Int = photoSet.count
    for i in 0...count{
        //use algorithm to display downloaded pictures in CollectionView.
        //If any image is nil do not display that image.
       //Same Code can be used to do the sum of all photos in each array.
    }


}

请记住,这不是最佳解决方案。应用程序的设计也无济于事,在同一屏幕上为20个用户加载图像是一个问题,除非图像真的很小,否则您将在那里运行。

我也建议您将此工作逻辑代码添加到方法中,该方法将为需要下载图像的每个用户调用Dispatch_get_global_queue,从而使其更加并行。

PS:如果您遇到任何问题,请告诉我,我们将很乐意为您提供帮助。