iOS その3 Advent Calendar
2日目を書かせていただきます!
今年は何記事書けるのかな...。
iOSということでSwiftのことではなくUIKit周りのことを書ければと思います。
といことで早速本題です。
UIImageの加工
先日作成したアプリで(S3とかにある)画像をたくさん並べる処理をして、案の定スクロールがカクツク問題にぶち当たりました。
その際に色々試したUIImageの加工について紹介します。
紹介する処理
- リサイズ
- 比率を保たない
- 比率を保つ
- 角丸
- ボーダー
あたりを紹介できればと思います。
リサイズ
UIImage+resize.swift
extension UIImage {
// 比率保つ版
func resize(_ size: CGSize) -> UIImage? {
let widthRatio = size.width / self.size.width
let heightRatio = size.height / self.size.height
let ratio = (widthRatio < heightRatio) ? widthRatio : heightRatio
let resizedWidth = round(self.size.width * ratio)
let resizedHeight = round(self.size.height * ratio)
let resizedSize = CGSize(width: resizedWidth, height: resizedHeight)
UIGraphicsBeginImageContextWithOptions(resizedSize, false, UIScreen.mainScreen().scale)
let drawRect = CGRect(origin: CGPointZero, size: resizedSize)
drawInRect(drawRect)
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage
}
// 比率保たない版
func resize(_ size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)
let drawRect = CGRect(origin: CGPointZero, size: resizedSize)
drawInRect(drawRect)
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage
}
}
注意点は特にありません...。
角丸
UIImage+maskCorner.swift
extension UIImage {
func maskCorner(radius r: CGFloat) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.mainScreen().scale)
let rect = CGRect(origin: CGPointZero, size: self.size)
UIBezierPath(roundedRect: rect, cornerRadius: r).addClip()
drawInRect(rect)
let clippedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return clippedImage
}
}
注意点は特にありません...。
ボーダー
UIImage+drawBorder.swift
extension UIImage {
func drawBorder(width borderWidth: CGFloat, color: UIColor) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)
// clip corner
let rect = CGRect(origin: CGPointZero, size: self.size)
let context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context!)
drawInRect(rect)
CGContextRestoreGState(context!)
let insetRect = CGRectInset(rect, borderWidth / 2.0, borderWidth / 2.0)
let path = UIBezierPath(rect: insetRect)
color.setStroke()
path.lineWidth = borderWidth
path.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
補足
ちなみにこのUIImageの加工の処理はメインスレッド以外でも実行できます。
なのでUICollectionViewCellなどでSDWebImageと一緒に使う場合はダウンロード処理が終わった後Cellのサイズに合わせてリサイズした後に表示処理をするとスクロールの邪魔もしづらくなります。(個人の体感ですが...)
終わりに
UICollectionViewCellのlayerをいじるよりだいぶ邪魔しないで済む方法になるかと思います。
ただ、もしできることならS3などの画像をリクエストでリサイズできるようお願いするともっと幸せになれるかもしれないです。
以上になります。