Reputation: 574
I'm trying to make a thumbnail image of UIImage
from PHLivePhoto so that I can get a moment before or after the picture captured. I'm struggling with the error:
unexpectedly found nil while unwrapping an Optional value
at
cgImage = try? imgGenerator.copyCGImageAtTime(CMTimeMake(avAsset.duration.value / 3, avAsset.duration.timescale), actualTime: nil)
I'm very new to swift2 syntax. please help me to get the thumbnail.
func makeThubnailsFromLivePhoto(livePhoto: PHLivePhoto) -> UIImageView {
let assetResource = PHAssetResource.assetResourcesForLivePhoto(livePhoto)
let avAsset = AVURLAsset(URL: NSURL(fileURLWithPath: assetResource[1].assetLocalIdentifier))
var err: NSError? = nil
let imgGenerator = AVAssetImageGenerator(asset: avAsset)
var cgImage: CGImage?
var imageView: UIImageView?
cgImage = try? imgGenerator.copyCGImageAtTime(CMTimeMake(avAsset.duration.value / 3, avAsset.duration.timescale), actualTime: nil)
let uiImage = UIImage(CGImage: cgImage!)
imageView = UIImageView(image: uiImage)
imageView!.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width/2, height: self.view.bounds.height/2)
return imageView!
}
Upvotes: 0
Views: 484
Reputation: 23449
As @RobNapier said to you in his very good answer, is very improbable that your error resides in the following line:
cgImage = try? imgGenerator.copyCGImageAtTime(CMTimeMake(avAsset.duration.value / 3, avAsset.duration.timescale), actualTime: nil)
According to Apple:
You use
try?
to handle an error by converting it to an optional value. If an error is thrown while evaluating thetry?
expression, the value of the expression isnil
.
Your error definitely is in this line:
let uiImage = UIImage(CGImage: cgImage!)
You can fix it using optional chaining like in the following way:
cgImage = try? imgGenerator.copyCGImageAtTime(CMTimeMake(avAsset.duration.value / 3, avAsset.duration.timescale), actualTime: nil)
if let cgImage = cgImage {
let uiImage = UIImage(CGImage: cgImage)
// do the rest of your code here to return the UIImage
}
else {
// was an error and you need to return nil or something else
}
Or you can use the new guard
statement like in the following way:
cgImage = try? imgGenerator.copyCGImageAtTime(CMTimeMake(avAsset.duration.value / 3, avAsset.duration.timescale), actualTime: nil)
guard let cgImage = cgImage else {
// here you need to return nil or something else you want to know the caller of the function that there was an error
}
let uiImage = UIImage(CGImage: cgImage)
imageView = UIImageView(image: uiImage)
imageView!.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width/2, height: self.view.bounds.height/2)
return imageView!
It's up to you what to use. I hope this help you.
Upvotes: 0
Reputation: 299605
Are you sure that's the line that raises the error? I would much more expect that it's this line:
let uiImage = UIImage(CGImage: cgImage!)
That's going to crash any time there's an error creating the image. You either need to use do/try/catch here to catch the errors and deal with them, or you need to use guard-let
to validate that cgImage
is not nil. Any time you use !
, you're saying "I bet my program's life that this is not nil."
Similarly, this line doesn't make sense:
var imageView: UIImageView?
You later assign imageView
from a constructor that cannot fail. But it causes you to use imageView!
, which could be dangerous (it happens not to be in this case, but it's hard to know that). Avoid !
as much as you can.
In general, you should avoid this pattern of var x: Type?
followed by x = ...
. Instead, use the pattern let x = ...
Type inference is an important part of Swift.
Upvotes: 1