【问题标题】:Sample code changed to guard and pointing out the crash示例代码更改为守卫并指出崩溃
【发布时间】:2017-03-06 06:36:10
【问题描述】:

这是我的代码

func numberOfSections(in collectionView: UICollectionView) -> Int
{
    return 1
}


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    return self.getVideosArray.count
}


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    //let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FullImageCell", for: indexPath) as! FullImageCollectionViewCell

     guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FullImageCell", for: indexPath) as? FullImageCollectionViewCell else {
        fatalError()
    }

    let indexPath = indexPath.row
    //UserDefaults.standard.set(indexPath, forKey: "INDEX")
    //UserDefaults.standard.synchronize()

    self.value = indexPath

    let videoStr = NSString.init(format: "http://52.2.212.171/wallpaper/admin/%@", self.getVideosArray.object(at: indexPath) as! String)
    self.downloadVideoLinkAndCreateAsset(videoStr as String)

    return cell
}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize
{
    return CGSize(width: self.collectionView.frame.size.width, height: self.collectionView.frame.size.height)
}


func downloadVideoLinkAndCreateAsset(_ videoLink: String)
{
    self.bgView.isHidden = false
    // use guard to make sure you have a valid url
    guard let videoURL = URL(string: videoLink) else { return }

    let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    // check if the file already exist at the destination folder if you don't want to download it twice
    if !FileManager.default.fileExists(atPath: documentsDirectoryURL.appendingPathComponent(videoURL.lastPathComponent).path) {

        // set up your download task
        URLSession.shared.downloadTask(with: videoURL) { (location, response, error) -> Void in

            // use guard to unwrap your optional url
            guard let location = location else { return }

            // create a deatination url with the server response suggested file name
            let destinationURL = documentsDirectoryURL.appendingPathComponent(response?.suggestedFilename ?? videoURL.lastPathComponent)
            do {

                try FileManager.default.moveItem(at: location, to: destinationURL)

                self.loadVideoWithVideoURL(destinationURL)
            }
            catch let error as NSError
            {
                print(error.localizedDescription)
            }

        }.resume()
    }
    else
    {
        let getPathUrl = documentsDirectoryURL.appendingPathComponent(videoURL.lastPathComponent)

        self.loadVideoWithVideoURL(getPathUrl)
    }

}


func loadVideoWithVideoURL(_ videoURL: URL) {
    let asset = AVURLAsset(url: videoURL)
    let generator = AVAssetImageGenerator(asset: asset)
    generator.appliesPreferredTrackTransform = true
    let time = NSValue(time: CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)/2, asset.duration.timescale))
    generator.generateCGImagesAsynchronously(forTimes: [time]) { [weak self] _, image, _, _, _ in
        if let image = image, let data = UIImagePNGRepresentation(UIImage(cgImage: image)) {
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let imageURL = urls[0].appendingPathComponent("image.jpg")
            try? data.write(to: imageURL, options: [.atomic])

            let image = imageURL.path
            let mov = videoURL.path
            let output = FilePaths.VidToLive.livePath
            let assetIdentifier = UUID().uuidString
            let _ = try? FileManager.default.createDirectory(atPath: output, withIntermediateDirectories: true, attributes: nil)
            do {
                try FileManager.default.removeItem(atPath: output + "/IMG.JPG")
                try FileManager.default.removeItem(atPath: output + "/IMG.MOV")

            } catch {

            }
            JPEG(path: image).write(output + "/IMG.JPG",
                                    assetIdentifier: assetIdentifier)
            QuickTimeMov(path: mov).write(output + "/IMG.MOV",
                                          assetIdentifier: assetIdentifier)

            guard let targetSize = self?.collectionView.bounds.size else
            {
                fatalError()
                //return
            }

            PHLivePhoto.request(withResourceFileURLs: [ URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.MOV"), URL(fileURLWithPath: FilePaths.VidToLive.livePath + "/IMG.JPG")],
                                placeholderImage: nil,
                                targetSize: targetSize,
                                contentMode: PHImageContentMode.aspectFit,
                                resultHandler: { (livePhoto, info) -> Void in

                                    guard let indexValue = self?.value else
                                    {
                                        fatalError()
                                        //return
                                    }

                                    let indexPath = IndexPath.init(row: indexValue, section: 0)
                                    print(indexPath)

                                    guard let cell = self?.collectionView.cellForItem(at: indexPath as IndexPath) as? FullImageCollectionViewCell
                                    else
                                    {
                                        fatalError()
                                        //return
                                    }
                                    cell.fullImage.livePhoto = livePhoto

                                    self?.bgView.isHidden = true
                                    //self?.livePhotoView.livePhoto = livePhoto

                                    //self?.collectionView.reloadData()
            })
        }
    }
}

在这里,我在 loadVideoWithVideoUrl 函数的单元格中设置实时照片。我更改为从 !守卫。并且应用程序在 func loadVideoWithVideoURL(_ videoURL: URL) 结束时崩溃,我将值设置为单元格。

guard let cell = self?.collectionView.cellForItem(at: indexPath as IndexPath) as? FullImageCollectionViewCell
                else
                 {
                     fatalError()
                      //return
                 }

【问题讨论】:

  • 崩溃日志说明了什么?
  • 日志显示:致命错误:在展开可选值时意外发现 nil
  • 如果行数为 2 则应用不会崩溃。
  • 你的阵列数量是多少?
  • 取决于服务器端。但不会超过 12。

标签: ios swift3 crash uicollectionviewcell


【解决方案1】:

我怀疑你的崩溃是因为这行中的!:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FullImageCell", for: indexPath) as! FullImageCollectionViewCell

改成:

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FullImageCell", for: indexPath) as? FullImageCollectionViewCell else {
  fatalError()

  return
}

如果它在执行fatalError() 行时崩溃,那么问题是cell 到FullImageCollectionViewCell 的转换失败。

【讨论】:

  • 我是否也需要在 loadVideowithVideoURL func 中保护单元格
  • 如果您不知道崩溃发生在哪一行,是的,我会使用guard 方法在您当前使用! 的任何地方展开。
  • 是的,应用程序因 fatalError() 语句而崩溃。
  • 现在更仔细地查看您的所有代码,我发现您使用! 解包的地方不止这两个地方。您能否编辑您的问题以显示您的示例代码已更改为 guard 并指出发生崩溃的确切位置?
  • 我认为您在故障点传递的indexPath 在那一刻不存在于collectionView 中。尝试在else 块中打印indexPath 并在那里设置断点。当断点触发时,将该数字与您的dataSource(我认为是getVideosArray)进行比较,看看它是否存在。此外,我认为当您想更新您的collectionView 时,更改您的dataSource 首先 然后collectionView.reloadData() 会是一种更好的方法。
猜你喜欢
  • 2013-03-31
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
相关资源
最近更新 更多