SwiftUI + Verge

In the development of the app that is kind of SNS or large application, it can often grow in complexity due to display a massive number of a state(data) correctly that scattered across many UI components.

Primarily, UIKit applications differ with Data-driven UI frameworks such as React and Vue, it functions as Event-driven, and each component(e.g., UIView) has a state itself. This means the number of the state that we should handle is so much larger than Data-driven application.

In this article, I introduce this framework Verge in iOS app development and what it allows us.

Manages the state with Store-pattern

Lately, Flux state management…


この記事は「Eureka Advent Calendar 2020」1日目の記事です。

Head of iOS & Pairs iOSアプリ開発責任者のMuukiiです。
本記事ではPairs iOSアプリとPairs Engage iOSアプリが活用している状態管理の方法についてお話します。

この記事はFlux等のUnidirectional-data-flowについてある程度の知識と経験がある方向けとなっています。


The bulletproof UI, this word from Storybook.
Storybook is a library for developing UI components in web applications.
This gives us a place to create UI where is detached from the main application.
This is the main purpose of this library.

Today, we’ve created a library for iOS application development inspired by the original Storybook.

Making a place to create UI where is detached from the main application

Storybook-ios absolutely inherits the main purpose of the original Storybook

Making a place to create UI where is detached from the main application

Technically, we can get this with creates a new application beside of main application to launch Storybook. And then import the UI…


Creating UI Component using Texture + TextureSwiftSupport

In this article, I’m going to talk about “Creating UI with code and how we could write like SwiftUI’s syntax with Texture

As a premise, the targets people in this article:

  • Trying to create UI without Interface Builder. (It means writing the code to set the layout constraints up.)
  • And feels tired with so many constraints and hard to recognize a layout from the source-code.

About creating UI with the code.

What can we get from creating UI without Interface-Builder?
That means writing setting AutoLayout up or managing the frame of view or layer manually.

In a massive project, it would have so many screens and…


(最終更新日:2020/12/01)

この記事は「eureka Advent Calendar 2019」16日目の記事です。

15日目はPairs JP Web Teamの新(@ooDEMi)による「Building Design System for Pairs」でした。

エウレカのiOSエンジニアのMuukiiです🤠
Pairsの日本版と台湾・韓国版 iOSアプリの開発を担当しております。

今回はSwiftUIとそのためのアプリケーション設計についてお話をします。

Pairs全体的に利用しているVergeというフレームワークの運用と開発による知見からの考察となります。

2019年はWWDCでSwiftUIが発表されて大きな話題となっています。
もちろんエウレカの中でもSwiftUIについて研 …


Pairs事業部のiOSエンジニアの木村です。

この度、Pairs の iOSアプリ Version 81.0.0にて発生した問題である、

「Pairs(v81.0.0)をインストールすることでiOSの設定アプリが強制終了してしまう問題」

この事象についての技術的な解説を行います。

また、今回発生した問題についてはこちらの記事にて解消方法が記載されておりますが、

現在公開されている最新のバージョン(v82.0.0)ではこの問題は解消しておりますので、現在も問題でお困りの方がいらっしゃいましたらAppStoreにてPairsのバージョンアップをお試しください。

こちらにつきまして、ご迷惑をおかけしたことをお詫び申し上げます。

発生した問題について

問題の事象についての詳細は次のとおりです。

  • Pairs(v81.0.0)をインストールすることでiOSの設定アプリが強制終了する問題が発生する
  • Pairs(v81.0.0)をiOSからアンインストールすることでこの問題は解消する。

なにが原因だったか

結論としては、Settings.bundle内に配置するplistに無効な値が入っていたことが原因でした。

こちらを詳しく解説します。

インストールされるすべてのiOSアプリは、iOSの設定アプリにアプリごとの設定画面を持つことができ、その項目として一覧に表示されます。

この設定画面には任意の項目を追加することが可能で、そのためにはSettings.bundleを作成しアプリに同梱します。

Pairs iOSアプリでは、この設定画面にてOSSのライセンス表示を行うために利用しています。

OSSごとにライセンス表示を行うため、OSSをタップすると、ライセンス表示の画面に遷移する、 List - Detail 型のUIになるように設定をしていました。

実際には次のようなスキーマです。

正しい状態のplist

今回、このarrayの中に無効な値が入ってしまいました。

無効な値 <string></string> が混入しているplist

これが原因で、設定アプリが強制終了したと考えています。


この記事は、開発するiOSアプリの中で、レイアウトパフォーマンスを上げるため、部分的にAutoLayout以外のレイアウトエンジンを用いた場合に、どのようにAutoLayoutの世界と接続することが出来るか。という考察です。

考え方の基本として、AutoLayoutからしたらその他のレイアウトエンジンはFrameベースで行うマニュアルレイアウトと同じものになるので、

AutoLayoutの制約の中でマニュアルレイアウトで作られたカスタムUIViewのコンポーネントを正しく動かすには?

を考えることになります。

先に結論

考察の結論として、スッキリしたものではないが、

  • マニュアルレイアウトで作られたカスタムコンポーネントはUILabelのサブクラスを使う
  • UILabelの持つtextRectメソッドをOverrideし、自身が膨張可能な幅を知り高さを計算しAutoLayoutに返却

この手法でマニュアルレイアウト(カスタムレイアウトエンジン)とAutoLayoutを概ね問題なく接続できた。

(概ねというのは、実装を試した時に特定のパターンでうまく動作しなかったことがあったため。)

以下、解説となります。

最大の幅を知り、高さを計算するにはどうする?

すべてのレイアウトエンジンはコンポーネントが持つコンテンツ制約をもとにサイズを計算する機能を持ちます。

コンテンツと制約とは例として、

Labelが持つテキストに応じて、「Widthが200ptのときにHeightは何pt?」

というイメージです。

幅が確定した時の高さがとても大切になります。


こんにちは iOSエンジニアの muukiiです🤠

今回はView(UI)コンポーネントの開発のアイデアのひとつを紹介します。

私の経験に基づいた事例として、Viewコンポーネントのユースケースとして次のようなものがありました。

  • 単体で使用される (Viewにそのまま貼り付け)
  • UICollectionViewまたはUITableViewで複数表示される (Cellとして表示)
  • タップ可能
  • 配置する場所による見た目の変化は無し

このようなケースにたまに遭遇することがあります。

この場合Viewコンポーネントはどのように設計し、実装すべきでしょうか。

コンポーネントが持つ機能や目的は同じだとするとコードの共通化は狙えそうです。

しかし、UICollectionViewまたはUITableViewが表示先だとUICollectionViewCellまたはUITableViewCellを継承したコンポーネントにする必要があります。

また、UICollectionViewCellを継承するとUITableViewには表示できなくなりますし、UIViewに貼り付けることも困難になります。

出来れば、使う場所に依存しない形でViewコンポーネントを用意したいものです。

まずは、UIViewサブクラスとしてViewコンポーネントを作り、単体で生成可能にする

UIViewのサブクラスだと安心しますね。initを呼べばいつでも生成可能です。

任意のViewコンポーネントを貼り付けられるUICollectionViewCellを作る

対象をUICollectionViewに表示することを例として、

ViewコンポーネントはUICollectionViewCellとして作る必要があるように見えますが、実はそうでもなく、中身が空のUICollectionViewCellを作り、そこにUIViewベースのコンポーネントを貼り付ければ表示は可能となります。

普段UIImageViewやUILabelを貼り付けているのと全く同じことと言えます。

コードで表現すると次のように実装することが出来ます。

これだけのことではあるのですが、MyViewContainerCell があまりにもただのコンテナ過ぎて、直接UICollectionViewCellサブクラスに実装することが多いと思います。

しかし、ただのコンテナ でもとても大きな価値があります。

この存在により中身であるMyViewがどこにでも表示できるコンポーネントでいられるようになるからです。

あえてデメリットを挙げるとすると、UICollectionViewCellに直接実装するよりもUIViewが一枚増えてしまうことです。
ただ、これが問題になることはほとんどないと言えるでしょう。

”ただのコンテナ” を少し一般化することを考えてみる

Viewコンポーネントを包むContainerCellを都度作るのは少し大変です。

Swiftの言語機能を活用して一般化することが出来ないかを考えてみます。

WrapperCellというUICollectionViewCellを用意しました。

WrapperCellは指定されたViewコンポーネントを自身と同じサイズで貼り付けて表示するだけの「ただのコンテナ or ラッパー」です。

WrapperCellはBackingViewMakerを持つ型をMakerとして受け付けます。

BackingViewMakerはWrapperCellが持つ中身のViewを生成する機能を持つことを表すprotocolです。

BackingViewMakerはどんなViewを生成するかassociatedTypeで指定可能ですが、そのViewはReusableViewTypeを実装していなければなりません。

ReusableViewTypeはWrapperCellに埋め込まれるViewが持つ必要があり、これはreuseされるタイミングを通知してもらうために必要なprotocolです。

チュートリアルとして、UIViewサブクラスとしてViewコンポーネントを実装します。

定義したMyViewをWrapperCellを通してCollectionViewに表示できるように登録します。

Cellをdequeueします。

WrapperCellはupdateメソッドを持っています。

updateメソッドを呼び出すことで、WrapperCellが持つ中身のViewにアクセスすることが可能となります。 (普通にpropertyアクセスしても全然問題ないです)

WrapperCellつかうとプロジェクト内におけるUICollectionViewCellサブクラスはWrapperCellのみになる

WrapperCellを使うことでどんなViewもreuseを考慮しながらUICollectionViewに表示できるようになりました。

こうなると、プロジェクト内に存在するUICollectionViewCellのサブクラスはWrapperCellだけで済むようになります。

さらにCellとして表示したいコンポーネントはUIViewサブクラスで開発可能になるので、どこにでも表示可能になります。

デザイン実装のために どこかに単体で貼り付けておき、 Build & Runのサイクルを高めるのにも役立ちそうです。

余談 : このアイデアはTextureから考えました


a wall of a container

この記事は eureka Advent Calendar 2018 2日目の記事です。

こんにちは、Pairs Global事業部のiOSエンジニアのmuukiiです 🤠

今回はクライアントサイドにおけるデータの保管方法についての話をします。

最近ではGraphQLやProtocol Buffersなどの利用機会が増え、サーバーAPIが返却するレスポンスは美しくネストされた構造化が進んでいます。

構造化を行うことは反復的な表現を表すのに優れ、ネーミングの明快さを向上し、データを見やすく保つことに貢献します。

GitHub API v4 GraphQLを用いたレスポンス

レスポンス構造と保存時の構造は必ずしも一致するわけではない

しかし、このような構造はあくまで通信先にデータを渡すときに作り上げられるものであり、レスポンス構造と保存時の構造は必ずしも一致するわ …

Muukii (Hiroshi Kimura)

iOS Engineer & Head of iOS at Eureka, Inc. https://twitter.com/muukii_app

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store