iOS Tips集 2

こんにちは。エンジニアの井戸田です。
Cluexでは7月に「ままのて」という、 妊娠、育児に関する医師監修のQ&Aやメッセージをお届けするアプリをローンチしました。

前回iOS Tips集 第1弾を書きました。第1弾はこちらの記事になります。 cluex-developers.hateblo.jp

今回はその第2弾になります。Nativeチームから集めた知識を文章化しました。

NavigationBarを透過、borderを消す方法

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // 処理
        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
    }
}

StatusBarの文字色を白にする

storyboard、コードで変更することは可能ですが、1つ1つ全てのViewControllerに対してやらなくてはいけません。
以下の方法では一回の設定で全てのViewControllerのStatusBarの文字を白にすることができます。

TARGETSのinfoに追加する。

key: View controller-based status bar appearance
Value: No

key: Status bar style
Value: UIStatusBarLightContent

画像に合わせてアスペクト比を変更

表示した画像のアスペクト比が異なる場合、StroyboardのAspect Rationは使えません。
ソースコード上で画像のアスペクト比を変更させることができます。

  1. NSLayoutConstraint というクラスを使用して制約を設定する。
imageView.image = image

let constraint = NSLayoutConstraint(item: imageView,
                                    attribute: .height,
                                    relatedBy: .equal,
                                    toItem: imageView,
                                    attribute: .width,
                                    multiplier: (response.value?.size.height)! / (response.value?.size.width)!,
                                    constant: 0)

NSLayoutConstraint.activate([constraint])
  1. storyboardの方でUIImageViewの上下左右の制約をかける。ここではアスペクト比やwidth, heightの制約はかけません。
  2. tableView:estimatedHeightForRowAtIndexPath メソッドで UITalbeViewAutomaticDimension を返す。
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: indexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

ref.) http://crossbridge-lab.hatenablog.com/entry/2016/02/29/125917

NavigationBarに複数のボタン配置した時の隙間を無くす

図1のようにナビゲーションバーに複数ボタンを入れる場合、以下のようにするとボタンの間に隙間が開いてしまう。

func setupNavigationItem() {
    let starIcon = UIImage.fontAwesomeIcon(name: .starO, textColor: .darkGray, size: CGSize(width: 36, height: 36))

    let icons: [UIBarButtonItem] = [
        UIBarButtonItem(image: starIcon, style: .plain, target: self, action: nil),
        UIBarButtonItem(barButtonSystemItem: .action, target: self, action: nil)
    ]

    navigationItem.rightBarButtonItems = icons
}

f:id:cluex-developers:20171011111208p:plain
図1

図2のように隙間をなくす場合、一度UIButtonに入れてあげてからsizeToFit関数を呼んでUIBarButtonItemにしてあげることで隙間がなくなる。

func setupNavigationItem() {
  let starIcon = UIImage.fontAwesomeIcon(name: .starO, textColor: .darkGray, size: CGSize(width: 36, height: 36))

 let icons: [UIBarButtonItem] = [
      translateBarButtonItem(icon: starIcon),
      UIBarButtonItem(barButtonSystemItem: .action, target: self, action: nil)
  ]

 navigationItem.rightBarButtonItems = icons
}

private func translateBarButtonItem(icon: UIImage) -> UIBarButtonItem {
    let button = UIButton()
    button.setImage(icon, for: .normal)
    button.sizeToFit()
    return UIBarButtonItem(customView: button)
}

f:id:cluex-developers:20171011111216p:plain
図2

UIStackViewに背景色を付ける

UIStackViewにはUIViewが内包されておりません。
UIStackView自体に背景色を付けるためにはUIStackView内にViewをaddSubviewをする必要があります。

まずaddSubviewするUIViewのConstraintsを制御するExtensionを切ります。

extension UIView {
    func pin(to view: UIView) {
        NSLayoutConstraint.activate([
          leadingAnchor.constraint(equalTo: view.leadingAnchor),
          trailingAnchor.constraint(equalTo: view.trailingAnchor),
          topAnchor.constraint(equalTo: view.topAnchor),
          bottomAnchor.constraint(equalTo: view.bottomAnchor)
          ])
      }
}

上記のExtensionは該当するUIViewを引数のUIViewに対して、スペース無く一面に広げる制約を付与します。
下記はUIViewControllerの一例です。
UIStackViewにUIViewを挿入し、最後にpinでUIStackViewのサイズに広げています。

class ViewController: UIViewController {
    @IBOutlet weak var stackView: UIStackView!

    private lazy var backgroundView: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        pinBackground(backgroundView, to: self.view)
    }

    private func pinBackground(_ view: UIView, to stackView: UIStackView) {
        view.translatesAutoresizingMaskIntoConstraints = false
        stackView.insertSubview(view, at: 0)
        view.pin(to: stackView)
    }
}

ref.) https://useyourloaf.com/blog/stack-view-background-color/

We're hiring!!

弊社ではWeb / ネイティブアプリエンジニアを募集しております。
ご興味がありましたらお気軽にご連絡下さいませ!
エンジニアの方、ぜひ情報交換しましょう!

www.wantedly.com

www.wantedly.com