【问题标题】:Load image from URL on WatchKit从 WatchKit 上的 URL 加载图像
【发布时间】:2015-04-05 15:47:59
【问题描述】:

在手表上加载外部图像是否有比以下更优雅的解决方案?

let image_url:String = "http://placehold.it/350x150"

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    let url:NSURL = NSURL(string:image_url)!
    var data:NSData = NSData(contentsOfURL: url)!
    var placeholder = UIImage(data: data)!

    // update ui
    dispatch_async(dispatch_get_main_queue()) {
        self.imageView.setImage(placeholder)
    }
}

【问题讨论】:

    标签: swift watchkit apple-watch


    【解决方案1】:

    NSURL 用于本地文件。而是使用 NSURLSession。设置远程图像的比例也很有用。

    import WatchKit
    
    public extension WKInterfaceImage {
    
        public func setImageWithUrl(url:String, scale: CGFloat = 1.0) -> WKInterfaceImage? {
    
            NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) { data, response, error in
                if (data != nil && error == nil) {
                    let image = UIImage(data: data!, scale: scale)
    
                    dispatch_async(dispatch_get_main_queue()) {
                        self.setImage(image)
                    }
                }
            }.resume()
    
            return self
        }
    }
    

    这样使用

    self.imageView.setImageWithUrl(image_url, scale: 2.0)
    

    【讨论】:

    • 这是正确答案。除非您使用 NSURLSession,否则图像不会显示在设备上。 +1
    • 此代码适用于从 http 或 https 加载图像,但您能否分享从本地文件存储 url 加载图像的代码?例如file:///private/var/mobile/Containers/Shared/AppGroup/CB69B2CD-3D2A-4428-9633-56385B28FEA0/Library/MMS/wi2gb8bahijqonom3dvsq.png
    【解决方案2】:

    这是分类

    import WatchKit
    
    public extension WKInterfaceImage {
    
        public func setImageWithUrl(url:String) -> WKInterfaceImage? {
    
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
                let url:NSURL = NSURL(string:url)!
                var data:NSData = NSData(contentsOfURL: url)!
                var placeholder = UIImage(data: data)!
    
                dispatch_async(dispatch_get_main_queue()) {
                    self.setImage(placeholder)
                }
            }
    
            return self
        }
    
    }
    

    这样使用

     self.imageView.setImageWithUrl(image_url)
    

    【讨论】:

      【解决方案3】:

      我认为该解决方案很好,因为它可以帮助您的应用程序在您尝试从网络加载一些图像时摆脱滞后。 你可以像这样创建一个新函数:

      func loadImage(url:String, forImageView: WKInterfaceImage) {
      // load image
          let image_url:String = url
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
              let url:NSURL = NSURL(string:image_url)!
              var data:NSData = NSData(contentsOfURL: url)!
              var placeholder = UIImage(data: data)!
      
      // update ui
              dispatch_async(dispatch_get_main_queue()) {
                  forImageView.setImage(placeholder)
              }
          }
      
      }
      

      之后你想从 urlString 加载图像的任何地方都可以这样使用:

      loadImage("http://...", forImageView: self.myImageView)
      

      希望对您有所帮助。

      【讨论】:

      • 谢谢。也许我们应该把它变成一个类别……
      • 如何添加 loading-completion-handler?
      【解决方案4】:

      我认为通过这个解决方案,您可以将图像存储在缓存中并从缓存中显示图像。所以您可以调用此函数并使用它。

      func loadImage(url:String, forImageView: WKInterfaceImage) {
      
          forImageView.setImageNamed("placeholder")
          let image_url:String = url
      
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
      
              let url:NSURL = NSURL(string:image_url)!
              print(url)
      
              //if image is already stored in cache
              if WKInterfaceDevice.currentDevice().cachedImages[image_url] != nil{
                  dispatch_async(dispatch_get_main_queue()) {
                      forImageView.setImageNamed(image_url)
                  }
              }else{
                  if let data = NSData(contentsOfURL: url){
      
                      //load image
                      let image = UIImage(data: data)!
                      //Store image in cache
                      WKInterfaceDevice.currentDevice().addCachedImage(image, name: image_url)
                      dispatch_async(dispatch_get_main_queue()) {
                          forImageView.setImage(placeholder)
                      }
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        刚做了同样的任务,这里的答案对我有帮助,但我需要做一些修改。所以我想在这里分享常见答案的更新版本(没有任何强制解包)(应该与 Swift 4.2 一起使用):

        public extension WKInterfaceImage {
        
        public func setBackgroundImage(url: String) {
            let asyncQueue = DispatchQueue(label: "backgroundImage")
            asyncQueue.async {
                do {
                    if let url = URL(string: url) {
                        let data = try Data(contentsOf: url)
                        if let placeholder = UIImage(data: data) {
                            self.setImage(placeholder)
                        }
                    }
                } catch let error {
                    print("Could not set backgroundImage for WKInterfaceImage: \(error.localizedDescription)")
                }
            }
        }
        

        }

        【讨论】:

        • 这很有帮助!
        【解决方案6】:
        public extension WKInterfaceImage {
            public func setImageWithUrl(url:String, scale: CGFloat = 1.0) -> WKInterfaceImage? {
                URLSession.shared.dataTask(with: NSURL(string: url)! as URL) { data, response, error in
                    if (data != nil && error == nil) {
                        let image = UIImage(data: data!, scale: scale)
        
                        DispatchQueue.main.async() {
                           self.setImage(image)
                        }
                    }
                }.resume()
        
                return self
            }
        }
        

        【讨论】:

          【解决方案7】:
               if let url = NSURL(string: "http://google.net/img/upload/photo2.png") {
                      if let data = NSData(contentsOfURL: url){
          
                       imageWK.setImage(UIImage(data: data))
          
                  }
              }
          

          试试这个代码。 不要忘记在您的 Plist 中添加 NSTransportSecurity。

          【讨论】:

          • 与其他解决方案一样,此解决方案在我的 watchOS 模拟器中运行良好,但在设备上却不行。添加日志后,我看到第二个 if 语句返回 false。我使用的图片openweathermap.org/img/w/10d.png
          • 你可以试试这个异步图片加载:github.com/natelyman/SwiftImageLoader
          • 谢谢,我刚刚使用 NSURLSession 添加了另一个答案,它在模拟器和设备上都可以正常工作
          【解决方案8】:

          斯威夫特 4.2

          使用 URLSession、正确的 GCD@discardableResult 来消除 Result of call to '...' is unused 警告。

          plist
          App Transport Security Settings
          Allow Arbitrary Loads - YES

          如果您愿意,您可以在故事板中设置 100x100 的固定图像尺寸。

          let url = "https://i.imgur.com/UZbLC0Q.jpg"
          
          public extension WKInterfaceImage {
          
              @discardableResult public func setImageWithUrl(url:String, scale: CGFloat = 1.0) -> WKInterfaceImage? {
          
                  URLSession.shared.dataTask(with: NSURL(string: url)! as URL) { data, response, error in
                      if (data != nil && error == nil) {
                          let image = UIImage(data: data!, scale: scale)
          
                          DispatchQueue.main.async {
                              self.setImage(image)
                          }
                      }
                      }.resume()
          
                  return self
              }
          }
          

          打电话

          row.image.setImageWithUrl(url: url, scale: 1.0)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多