IBDesignable / IBInspectable で UIプロトタイピンガブル

53
IBDesignable / IBInspectable UI

Transcript of IBDesignable / IBInspectable で UIプロトタイピンガブル

IBDesignable / IBInspectable で

UIプロトタイピンガブル

自己紹介

@starfruits_j (Little Gleam)

自己紹介

@starfruits_j (Oshikawa)

自己紹介

hackadl

株式会社 Azione

元Webデザイナーのプログラマー、管理職

デコメーラー、モバスペブック

個人でもアプリ

Swift!?

Swift 採用決定!

Swift 2.0 採用決定!

Swift処理が高速化される!?

安全!

コーディングが高速化!

コーディングデザインばっかり考えてしまって進まない!

本題

IBDesignable / IBInspectable

使ってますか?

XCode 6 から使える

Interface Builder で修正できないものを変更可能に

変更内容を Interface Builder で確認できる

使い方

import UIKit

@IBDesignable class DesignableView: UIView {

@IBInspectable var cornerRadius: CGFloat = 0 {

didSet {

layer.cornerRadius = cornerRadius

}

}

}

Extension でも実装できます

! Extensions may not contain stored properties

Extension でも実装できます

※ (conputed propertyで)

extension UIView {

@IBInspectable var cornerRadius: CGFloat {

get {

return layer.cornerRadius

}

set {

layer.cornerRadius = newValue

if newValue > 0 {

layer.masksToBounds = true

}

}

}

}

やりすぎるとIBが大変

extensionは計画的に

他にもこんな値が割り振れます

* Bool

* Int

* CGFloat

* Double

* String

* CGPoint

* CGSize

* CGRect

* UIColor

* UIImage

プロトタイピングツールとして

Interface Builderを使う

去年くらいに話題になりました。

画像を登録して、UIImage.imageNamedにセットしたり

デザイナには少し敷居が高い

そもそも画像を用意するなら、Illustratorでおk

IBDesignableを使えば

より具体的なデザインが可能に

おすすめInspecterble

UIImageView.SVGNamed(named: String)

UIImage+SVG等を利用してSVGのファイル名から画像表示。

xmlから作成もできるかも

@IBDesignable class SVGImageView: UIImageView {

@IBInspectable var SVGNamed: NSString?

@IBInspectable var SVGImageSize: CGSize?

@IBInspectable var SVGColor: UIColor?

override func awakeFromNib() {

super.awakeFromNib()

let size = SVGImageSize ?? frame.size

image = UIImage(SVGNamed: SVGNamed,

targetSize: size,

fillColor: SVGColor)

}

}

UIImageView.iconFontNamed

FontAwesomeKitを利用してFontIconの名前で画像表示。

@IBDesignable class IconFontImageButton: UIButton {

@IBInspectable var iconFontNamed: String? {

didSet {

self.iconFont = IconFont(rawValue: iconFontNamed!)!

}

}

var iconFont: IconFont = .None {

didSet {

updateImage()

}

}

@IBInspectable var iconPoint: CGFloat = CGFloat.NaN {

didSet {

updateImage()

}

}

private func updateImage() {

let point = iconPoint.isNaN ? min(frame.size.width, frame.size.height) : iconPoint

let img = iconFont.image(point: point, outSize: frame.size)

enumが使えないのが残念。一個一個マッピングして使ってま

enum IconFont: String {

case None = "none"

case ArrowBack = "ArrowBack"

func image(point point: CGFloat, outSize: CGSize) -> UIImage? {

var icon: FAKIonIcons? = nil

switch self {

case .None:

break

case .ArrowBack:

icon = FAKIonIcons.iosArrowBackIconWithSize(point)

}

return icon?.imageWithSize(outSize)

}

}

UIButton.highlightedBackgroundColor

@IBDesignable class DesignableButton: UIButton {

@IBInspectable var highlightedBackgroundColor: UIColor?

private var defaultBackgroundColor: UIColor?

override var highlighted: Bool {

didSet {

if highlighted {

backgroundColor = highlightedBackgroundColor

} else {

backgroundColor = defaultBackgroundColor

}

}

}

override func awakeFromNib() {

super.awakeFromNib()

defaultBackgroundColor = backgroundColor

}

}

UIImageView.imageURLString

@IBDesignable class DesignableImageView: UIImageView {

@IBInspectable var imageURLString: String = "" {

didSet {

if let URL = NSURL(string: imageURLString) {

image = UIImage(data: NSData(contentsOfURL: URL)!)

}

}

}

}

※ レンダリングの処理が200msを超えるとtimeoutになります

あくまでも仮で表示したい場合に。

UIImageView.imageOrientation

@IBInspectable var imageOrientation: Int = 0 {

didSet {

let orientation = UIImageOrientation(rawValue: imageOrientation)!

image = UIImage(CGImage: image?.CGImage, scale: 0, orientation: orientation)

}

}

他にも

* UIButton.imageSize: insetで引き算するより使いやすい

* UIImageView.placeHolderImage: SDWebImage等の非同期読み込み時の画像

* gradation, gradationDirection: UIColor 2つ と グラデーションする方向

* cornerRadius: CGFloat

* borderCurcle: Bool

* backgroundBlur: Bool (未確認)

* borderColor

* shadowColor

* などなど

ところで

Swift 2.0 : 主な変更点

guard

defer

Error Handling

Protocol Extension

Swift 2.0 : 主な変更点

guard

defer

Error Handling

Protocol Extension

Protocol Extension

Protocolに実装を持たせられる

optionalなdelegateがSwiftでも書けるように

Appleが積極的に採用

クラス継承->プロトコル継承に

既存のクラスに横から差し込むように

実装を追加できる

注意点

インスタンス変数は作れない

既存コードのオーバーライドは無理

名前の衝突の可能性

global functionの代わりと考える

なんとかブルって名前が多い

Comparable, Reflectable, Printable, Sliceable...

こんなブルができたら

最高じゃないですか?

@IBDesignable class RoundizeView: UIView, Roundable {

}

BlurEffectable

@IBDesignable class AccountCell: UITableViewCell, BlurEffectable {

}

FontIconable

@IBDesignable class UserView: UIView, FontIconable {

}

できませんでした!

protocol Roundable: class {

var cornerRadius: CGFloat { get set }

}

extension Roundable where Self : UIView {

@IBInspectable var cornerRadius: CGFloat {

get {

return layer.cornerRadius

}

set {

layer.cornerRadius = newValue

if newValue > 0 {

layer.masksToBounds = true

}

}

}

}

@IBDesignable class RoundableView: UIView, Roundable {

override func awakeFromNib() {

super.awakeFromNib()

}

}

@IBDesignable class RoundableImageView: UIImageView, Roundable {

override func awakeFromNib() {

super.awakeFromNib()

}

}

理由

IBInspectableはinstance propertyにのみ設定可能

Protocol Extension にはインスタンス変数は作れない

extension ならcomputed propertyで可能です

おわり

Protocol Extensionについては Tomohiro Kumagai @es_kumagai

さんの資料が参考になります

Swift 2.0 大域関数の行方から #swift2symposium

プロトコル拡張の話? #WWDC21cafe

http://www.slideshare.net/tomohirokumagai54/swift-20-

49927701

http://www.slideshare.net/tomohirokumagai54/wwdc21cafe