作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含 5 个链接的数组,其中包含 jpg
或 mov
文件。我想将它们下载到我的 iOS Swift 应用程序中。我使用以下代码。
var index = 0
while (index < myLinks.count) {
if (myLinks[index].resource_type == "image") {
let stringURL = "http://www.blablabla" + ".jpg"
let url = NSURL(string : stringURL)
getDataFromUrl(url!) { (data, response, error) in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? url!.lastPathComponent ?? "")
print("Download Finished")
myLinks[index].image = UIImage(data: data)
}
}
else if (myLinks[index].resource_type == "video") {
let stringURL = "http://www.blablabla" + ".mov"
let url = NSURL(string : stringURL)
getDataFromUrl(url!) { (data, response, error) in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? url!.lastPathComponent ?? "")
print("Download Finished")
dispatch_async(dispatch_get_main_queue(), {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory : NSString = paths[0]
let appFile = documentsDirectory.stringByAppendingPathComponent(myLinks[index].id! + ".m4v")
do {
try data.writeToFile(appFile, options: .AtomicWrite)
myLinks[index].videoURL = NSURL(fileURLWithPath: appFile)
}
catch _ {
print("error saving video")
}
})
}
}
index = index + 1
}
func getDataFromUrl(url: NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
现在唯一的问题是,下载完这些资源后,我想以幻灯片的形式展示给用户,所以我只能知道5次下载都完成了才能继续。上面代码的问题在于,由于 getDataFromUrl
函数是异步执行的,所以这个 while 循环将在所有内容实际下载完成之前完成执行。
编辑
这是一个代码,它也使已接受的答案适应上传。问题是当队列中有多个值时,只有第一个任务被执行,然后什么也没有发生。
var uploadQueue:[UploadMessage]?
let session = NSURLSession.sharedSession()
let lockQueue = dispatch_queue_create("com.dsdevelop.lockQueue", nil)
func getRemainingActiveUploads() -> Int {
return (self.uploadQueue != nil) ? self.uploadQueue!.count : 0
}
func removeMessageFromUploadQueue(messageToBeRemoved : UploadMessage) {
if (uploadQueue != nil) {
dispatch_sync(lockQueue) {
self.uploadQueue = self.uploadQueue?.filter({$0.date!.compare(messageToBeRemoved.date!) == NSComparisonResult.OrderedSame})
}
}
}
var uploadTimer : NSTimer?
func finishedUploading() {
uploadTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(uploadAllLinks), userInfo: nil, repeats: false)
if (needToRefetch) {
needToRefetch = false
newMessageReceived()
}
}
func uploadAllLinks()
{
print("uploading test")
uploadTimer?.invalidate()
uploadTimer = nil
// suspending queue so they don't all finish before we can show it
session.delegateQueue.suspended = true
session.delegateQueue.maxConcurrentOperationCount = 1
let myUrl = NSURL(string: "http://****")
// create tasks
if (uploadQueue != nil) {
if (uploadQueue?.count > 0) {
for message in uploadQueue!
{
let request = NSMutableURLRequest(URL:myUrl!)
request.HTTPMethod = "POST"
request.timeoutInterval = 10
request.HTTPShouldHandleCookies=false
var postString = "sender=" + message.sender!
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let dltask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
if data != nil
{
do {
let jsonArray = try NSJSONSerialization.JSONObjectWithData(data_fixed!, options:[])
dispatch_async(dispatch_get_main_queue(), {
if let errorToken = jsonArray["error"] as! Bool? {
if !errorToken {
self.uploadQueue = self.uploadQueue!.filter({$0.date!.compare(message.date!) != NSComparisonResult.OrderedSame})
let remaining = self.getRemainingActiveUploads()
print("Downloaded. Remaining: \(remaining)")
if (remaining == 0) {
self.finishedUploading()
}
}
else {
let remaining = self.getRemainingActiveUploads()
print("Downloaded. Remaining: \(remaining)")
if (remaining == 0) {
self.finishedUploading()
}
}
}
else {
let remaining = self.getRemainingActiveUploads()
print("Downloaded. Remaining: \(remaining)")
if (remaining == 0) {
self.finishedUploading()
}
}
})
}
catch {
print("Error: \(error)")
}
}
})
print("Queuing task \(dltask)")
dltask.resume()
}
session.delegateQueue.suspended = false
}
else {
finishedUploading()
}
// resuming queue so all tasks run
}
}
最佳答案
使用 NSURLSession
及其底层 NSOperationQueue
的内置功能,您可以轻松地做到这一点。
import UIKit
class ViewController: UIViewController {
let MyDownloadsCompleteNotification:String = "MyDownloadsCompleteNotification"
var myLinks:[NSURL]?
var downloadQueue:[NSURL]?
let session = NSURLSession.sharedSession()
let lockQueue = dispatch_queue_create("com.dsdevelop.lockQueue", nil)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myLinks = [ NSURL(string: "https://pbs.twimg.com/profile_images/447374371917922304/P4BzupWu.jpeg")!,
NSURL(string: "http://www.telegraph.co.uk/content/dam/pets/2016/03/18/bunny-large_trans++qVzuuqpFlyLIwiB6NTmJwfSVWeZ_vEN7c6bHu2jJnT8.jpg")!,
NSURL(string: "http://4.bp.blogspot.com/-HTvSYzA-pO4/UgQb4Zh_u0I/AAAAAAAAEuI/XwhtogT_1tA/s1600/3+cute2.jpg")!,
NSURL(string: "http://cdn.shopify.com/s/files/1/0224/1915/files/bunny.jpg?22110")!,
NSURL(string: "http://vignette1.wikia.nocookie.net/hare/images/1/1f/Bunnies-bunny-rabbits-16437969-1280-800.jpg/revision/latest?cb=20130831183111")!
]
// Register to know when all downloads are done
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(allDownloadsComplete), name: MyDownloadsCompleteNotification, object: nil)
downloadAllLinks(myLinks!)
}
func allDownloadsComplete(n:NSNotification)
{
print("Awesome all downloads are done!")
}
func getRemainingActiveDownloads() -> Int
{
return (self.downloadQueue != nil) ? self.downloadQueue!.count : 0
}
func removeUrlFromDownloadQueue(url:NSURL)
{
if self.downloadQueue != nil
{
dispatch_sync(lockQueue) {
self.downloadQueue = self.downloadQueue!.filter({$0.absoluteString == url.absoluteString})
}
}
}
func downloadAllLinks(links:[NSURL])
{
// suspending queue so they don't all finish before we can show it
session.delegateQueue.suspended = true
session.delegateQueue.maxConcurrentOperationCount = 1
downloadQueue = links
// create tasks
for link in links
{
let dltask = session.downloadTaskWithURL(link, completionHandler: { (url, response, error) in
if let urlString = response?.URL?.absoluteString
{
self.downloadQueue = self.downloadQueue!.filter({$0.absoluteString != urlString})
let remaining = self.getRemainingActiveDownloads()
print("Downloaded. Remaining: \(remaining)")
if (remaining == 0)
{
NSNotificationCenter.defaultCenter().postNotificationName(self.MyDownloadsCompleteNotification, object: nil)
}
}
})
print("Queuing task \(dltask)")
dltask.resume()
}
// resuming queue so all tasks run
session.delegateQueue.suspended = false
}
}
关于ios - 从 URL Swift 异步下载和上传数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39151501/
我有以下正则表达式 /[a-zA-Z0-9_-]/ 当字符串只包含从 a 到z 大小写、数字、_ 和 -。 我的代码有什么问题? 能否请您向我提供一个简短的解释和有关如何修复它的代码示例? //var
我是一名优秀的程序员,十分优秀!