koogawa blog

iOS、Android、foursquareに関する話題

RxSwiftを使ってfoursquareのベニューを取得するメモ(Swift 3.0版)

以前書いたこちらの記事がさっそくビルドできなくなっていたので、Swift 3.0 対応版としてリライトしました。

blog.koogawa.com


RxSwift のメリットを理解するには実際に使ってみるのが一番!ということで、とりあえず foursquare のベニューを取得するサンプルを作ってみました。

f:id:koogawa:20160515223640p:plain

※RxSwift は絶賛勉強中なので間違ったことを書いている可能性が高いです。ツッコミ歓迎です!

動作環境

  • Swift 3.0
  • RxCocoa (3.0.0-rc.1):
  • RxSwift (3.0.0-rc.1)
  • SwiftyJSON (3.1.1)
  • Xcode 8.0

APIクライアント

APIにアクセスする部分を作ります。戻り値を Observable<[Venue]> にしているのがポイントです。

func search(query: String = "") -> Observable<[Venue]> {
    return Observable.create{ observer in
        let client = FoursquareAPIClient(accessToken: "YOUR_TOKEN")
        let parameter: [String: String] = [
            "ll": "40.7,-74",
            "query": query
        ];
        client.request(path: "venues/search", parameter: parameter) {
            [weak self] data, error in
            guard let strongSelf = self, let data = data else { return }
            let json = JSON(data: data)
            let venues = strongSelf.parse(venuesJSON: json["response"]["venues"])
            observer.on(.next(venues))
            observer.on(.completed)
        }
        return Disposables.create {}
    }
}

fileprivate func parse(venuesJSON: JSON) -> [Venue] {
    var venues = [Venue]()
    for (key: _, venueJSON: JSON) in venuesJSON {
        venues.append(Venue(json: JSON))
    }
    return venues
}

通信ライブラリは拙作 FoursquareAPIClient を使用しました。

ViewModel

ViewModel から先ほどの serch を呼び出す部分です。

public func fetch(query: String = "") {
    client.search(query: query)
        .subscribe { [weak self] result in
            switch result {
            case .next(let value):
                self?.venues.value = value
            case .error(let error):
                print(error)
            case .completed:
                ()
            }
        }
        .addDisposableTo(disposeBag)
}

search の戻り値が Observable<[Venue]> なので、これを subscribe することができます。その中で、返ってくる値(ベニューリストなど)を Variable 型の venues にセットしています。この venues は ViewController から bind されるため、値が変更されるタイミングで何か処理を発火させることができるわけです。

ViewController

ViewController は30行程と、かなりスッキリしました。rx.items(dataSource: ) でベニューリストと TableView を bind しているのがポイントです。ViewModel のベニューリストに変化があるとTableViewがリロードされます。

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    var viewModel = ViewModel()
    var dataSource = DataSource()
    var delegate = Delegate()
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self.delegate
        self.viewModel.fetch()

        self.viewModel.venues
            .asDriver()
            .drive (
                self.tableView.rx.items(dataSource: self.dataSource)
            )
            .addDisposableTo(self.disposeBag)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

完全なソースコードはこちらです。

GitHub - koogawa/RxSwiftSample: RxSwiftSample

参考にさせて頂いた記事など

CocoaPodsに登録した自作ライブラリを更新するメモ

毎回忘れるのでメモ。

前提

  • すでに自作ライブラリを CocoaPods に公開済み

最初にライブラリを公開する際は下記記事がとても参考になる。

手順

1. ライブラリを更新

変更内容を push しておく。

実際に pod install して使えるかテストしておくこと。ブランチ指定が便利。

pod 'FoursquareAPIClient', :git => 'https://github.com/koogawa/FoursquareAPIClient.git', :branch => 'develop'

1. podspec ファイルを編集

s.version を上げるのを忘れずに。

2. git にタグ追加

$ git tag -a 2.0.0 -m 'Compatible Swift 3.0'
$ git push origin 2.0.0

3. podspec をバリデーション

$ pod spec lint

なんか怒られたら直す。

Swift 3対応でちょっとハマったので下の方に対処法を書いておいた。

4. CocoaPodsへ公開

pod trunk push FoursquareAPIClient.podspec 

トラブルシューティング

困ったらとりあえず pod を最新に上げてみる

$ sudo gem install cocoapods

Swift 3 対応

pod spec lint したら次のエラーが出た。

Check dependencies
“Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.
“Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.

** CLEAN FAILED **


The following build commands failed:
    Check dependencies
(1 failure)

ググったら、同じように困っている人がいた。

Swift 3 CocoaPod does not pass lint - Stack Overflow

cocoapod を最新に上げて、.swift-version ファイルを追加しないといけないらしい。

↑これは解決したけど、また新たなエラーが。

pod trunk push: "xcodebuild: error: 'App.xcworkspace' does not exist." · Issue #5843 · CocoaPods/CocoaPods

で解決。

Swift 5 対応

pod spec lint したら次のエラーが出た。

    ** BUILD FAILED **
    
   Testing with `xcodebuild`. 
 -> FoursquareAPIClient (5.0.0)
    - ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code.
    - NOTE  | xcodebuild:  note: Using new build system
    - NOTE  | [iOS] xcodebuild:  note: Planning build
    - NOTE  | [iOS] xcodebuild:  note: Constructing build description
    - NOTE  | xcodebuild:  error: SWIFT_VERSION '3.0' is unsupported, supported versions are: 4.0, 4.2, 5.0. (in target 'App')
    - NOTE  | xcodebuild:  error: SWIFT_VERSION '3.0' is unsupported, supported versions are: 4.0, 4.2, 5.0. (in target 'FoursquareAPIClient')

Analyzed 1 podspec.

[!] The spec did not pass validation, due to 1 error.

SWIFT_VERSION3.0 なんか指定してないよ!と思ったけど、podspec ファイルに

  s.swift_version = '5.0'

を指定してないのが原因?

さらに、Swift 3 対応のときに追加した.swift-version ファイルも今は deprecated らしいので削除。

これでも解決しない場合は workaround だけど --allow-warnings オプションで回避できるらしい。

リンク

「理科系の作文技術」を読んだ

以前、id:hyoshiok さんのブログで紹介されており、ずっと気になっていたので読んでみました。

対象とする読者

「私がこの書物の読者と想定するのは、ひろい意味での理科系の、わかい研究者・技術者と学生諸君だ。これらの人たちが仕事でものを書くとき――学生ならば勉学のためにものを書くとき――に役立つような表現技術のテキストを提供したい」。

序章で著者がこう述べているように、本書は主に理系層がターゲットとなっています。 しかし、実際に読んでみると、文書を書くすべての人におすすめできる内容になっています。

以下、印象に残った内容をいくつか紹介していきます。(数字は章を表す)

読者を意識する(2.3.4)

書くことに慣れていない人は、誰が読むのかを考えずに書き始める傾向がある、と著者は述べています。

読者が誰であり、その読者はどれだけの予備知識を持っているか、またその文書に何を期待し、要求するだろうかを、十分に考慮しなければならない。

これは技術ブログを書く際にも通じると感じました。読者がプログラミング初心者なのか、それとも基本的なことは理解している中級者なのか。読者のレベルによっても書く内容は変わってくると思います。

目標規定文(2.4)

自分は何を目標としてその文書を書くのか、そこで何を主張しようとするのかを熟考して、それを一つの文にまとめる。そういう文を、この本では目標規定文と読んでいました。

私はふだん、業務用の文書(Wikiなど)を書く際に、「これは何」という段落を一番上に用意するようにしています。そこに文書の目的を書くことが多いのですが、これがまさに目標規定文なのかな、と思いました。これがあるだけで、読者は読む・読まないの判断ができるようになります。

まぎれのない文を(8.3)

黒い目のきれいな女の子

この文はなんと 8通り に読むことができます。(ロゲルギスト共著『第四物理の散歩道』、(岩波書店、1969)、p226より)

「読むことができる」と表現しましたが、それだけ読者に誤解を与えてしまう可能性があるとも言えます。

この例は読点を入れることでまぎれがなくなります。

  • 黒い目の、きれいな、女の子
  • 黒い、目のきれいな、女の子

一つの文を書くたびに、読者がどういう意味に取るだろうかと、あらゆる可能性を検討するべきです。

字面の白さ(8.5.1)

次の2つの文を比べてみてください。

  1. 電源電圧の変動は普通0.1%程度だが、これでは普通  10^-7 程度の周波数安定性しか得られない。我々の実験目的を達成するには、抵抗R1を調整して安定性を良くする必要がある。

  2. 電源電圧の変動はふつう0.1%程度だが、これではふつう  10^-7 程度の周波数安定性しか得られない。われわれの実験目的を達成するには、抵抗R1を調整して安定性をよくする必要がある。

パッと見たとき、A. は全体として黒く、B. はそれとくらべて白く感じられると思います。字面の白さとはそういう意味です。無駄に漢字を使うと文章に難解な印象を与えてしまうので、適切な白さにすべきです。

手紙(10.1)

まだ e-mail も普及していなかった時代なので、手紙で要件を伝える方法についても書かれています。

印象的だったのが、10.1.3 本文 の

私なら、情報伝達に関係のない「拝啓、時下ますます・・・」は省いて〜

の部分。

メール文化になった今も「○○様 お世話になっております。△△株式会社の・・・」から始まるメールで溢れており、この辺は今もあまり変わっていないですね。

「読む」のではなく「話す」(11.1)

最終章では学会講演の要領についても書かれています。ここは「学会講演」を「勉強会での発表」に置き換えて読みました。

講演では原稿を「読む」のは禁物だ。聞く立場になってみればすぐにわかることだが、ひとが原稿を読みあげるのについていくには非常な努力がいる。

これは確かにその通りで、例えば「真空中で400℃、2時間の熱処理をした試料の表面に金の電極を蒸着し、・・・」というような複文は、読めばスラスラとわかっても、聞く側になると結構つらいものがあります。

この例は「資料はあらかじめ真空中で400℃、2時間の熱処理をします。その試料の表面に金の電極を蒸着し・・・」と単文に分割することで救われそうです。しかし、著者も述べているように、原稿をただ読みあげるのではなく、多少下手でも一生懸命「自分の言葉」でオーディエンスに話しかけることが重要なのだと思います。

おわりに

出版が1981年ということもあり、中にはOHP(オーバーヘッドプロジェクタ)の使い方など、今ではあまり使われなくなった内容も含まれています。しかし、それ以外の内容は30年以上たった今でも十分通用すると思いました。もっと早くこの本に出会いたかった!

理科系の〜と銘打ってはいますが、文章を書くすべての人におすすめしたい一冊です。

#iosdc で "「まりも」とiOSの6年間" の話をしてきたよ

f:id:koogawa:20160821091002p:plain

8/19〜20、 練馬で開催された iOSDC Japan 2016 にスピーカー兼スタッフとして参加してきました。

発表した内容

iPhone OS 3時代にリリースした「まりも」アプリの進化とともに、iOSの歴史を皆で振り返っていく、というスタイルでした。

↑のスライドだとアニメーションしませんが、iOS 9より磨きがかかったまりもの回転 についても触れました。

iOS 8 までは矩形の衝突判定にしか対応していなかったのが、

f:id:koogawa:20160821090034g:plain

iOS 9 からは円形の衝突判定にも対応したのでした!

f:id:koogawa:20160821090101g:plain

Togetter さんに、発表中のツイートをまとめて頂きましたm( )m

今後もがんばります💪

お越しいただいた方ありがとうございました!

感想

スタッフとして

f:id:koogawa:20160821094450p:plain

今回は Track B のチームリーダー兼ストリーミング配信を担当しました。

  • 会場は暑くないか
  • 照明は明るすぎないか
  • スライドは見にくくないか
  • トークがタイムテーブル通りに進んでいるか
  • 配信は途切れていないか

などを常に気にしなければならなかったので、かなり忙しかった!残念ながら、ほとんどのトークは落ち着いて聞くことができませんでした。これからゆっくり録画を観たいと思います👍

スピーカーとして

f:id:koogawa:20160821094514j:plain (Thanks: Tecco)

やはり緊張していたこともあり、予定より数分早く終わってしまいました。知らないうちに早口になってしまうんだなぁ。聴きづらかったらすんません🙇🏻

また、今回はスピーカーのみなさまへ、お知らせとお願い | iOSDC Japan 2016にもあるように

トーク終了後のQ&Aタイムでは質問者にもマイクを渡して質問してもらいますが、録画や配信には質問者のマイクの音声は乗らないことがあります。必ず質問を復唱してからの回答をお願いします。例: 「○○というご質問ですね。それは〜」

というのをやってみたのですが、これがやってみると意外と難しい。途中からグダグダになってしまった気がします😫

あとで自分の発表を見て、今後に活かしたいと思います。

練馬について

「練馬ってどこにあるの?東京なの?」などとよく聞かれる練馬ですが、実は新宿や池袋に乗り換えなしでアクセスできる、とても良い位置にあるのですよ。私もかれこれ10年以上住んでいます。

id:ryo_pan さんのエントリにもあるように、美味しいラーメン屋もたくさんあるので、ぜひ近くに来たら寄ってみてください!

まとめ

一言でまとめると「最高」でした。

久しぶりに心の底から「超楽しい!!」と思えた2日間でした。

会場まで足を運んで頂いた皆さま、スポンサーの皆様、スタッフの皆さま、ありがとうございました!

2016/7/21 #potatotips #31 (iOS/Android開発Tips共有会) に参加してきたよ

f:id:koogawa:20160721235858p:plain

今日はFiNCさんで開催された potatotips #31 (iOS/Android開発Tips共有会) に参加してきました。

potatotips.connpass.com

噂では聞いていたのですが、とても綺麗なオフィスでした。

f:id:koogawa:20160722001424j:plain

ペッパーくんもいましたよ!

f:id:koogawa:20160722001231p:plain

懇親会のメニューも健康的!ごちそうさまでしたm( )m

f:id:koogawa:20160722014225p:plain

ツイートもまとめておきました。

以下は発表のメモになります。間違いなどあれば教えて下さい。


目次:

UICollectionViewでインタラクティブなCellの並び替え

元同僚である平松さんの発表です。 UICollectionView の Interactive Reordering が超便利だよ!というお話でした。

この機能、実は iOS 9 からあったそうなんですが、なかなか知られていないみたいです(自分も知らなかった)。

実装方法は、UIGestureRecognizer などと組み合わせて reorder を呼ぶだけ。 これだけで簡単にiOSのホーム画面のような実装ができるそうな。ぜひ使っていきたいですな!

UIPageViewControllerをつかって無限スクロールできるタブUIを実装した話

Vasily の EndoMari さんによる発表。 最近良く見るタブを横にスクロールできるUIを実装した時のお話でした。

この手のライブラリはたくさん出てるけど、ライフサイクルが把握しにくかったり、ログ集計が難しいという理由から、Vasilyさんでは自前で実装されたそうです。

http://tech.vasily.jp/entry/tab_page_viewcontrollertech.vasily.jp

iOSアプリ100個考察してみた(中間報告)

mafmoff さんによる発表です。iOSアプリ100個を考察してみて気付いたことについて語られていました。

github.com

iOSアプリ100個を考察してみて気付いたこと:

  • 設定画面が灰色!
  • 一覧スクロールでナビゲーションバーが引っ込むの多いよね
  • 横スクロールタブが多い(スマニュー風のやつ)
  • そのチュートリアルいる?すぐ使いたいのでスキップできないと辛み
  • WebViewの中にヘッダーがあって二重に表示されちゃってる
  • ライセンスをアプリの設定画面に表示しちゃってる →iOS標準の設定画面に表示してみては?

ひょっとすると、iOS標準の設定画面にアプリ独自の設定項目を置けることが意外と知られていないのかもしれませんね。

[iOS] アプリの設定画面にバージョン表記と謝辞を自動で設定する | DevelopersIO

Binding Realm

woxtu(おつ)さんによる発表。最初にアカウント名をどう発音するのか話題になりました。

Realm のオブジェクトを KVO を使って監視し、データが更新されたらViewにも反映させる方法について解説されていました。他にも SwiftBond, RxSwift などで実現できそうですが、KVO を推しているそうです。

SketchでUIを楽に組もう! - ZeplinとSympli -

d_date さんによる発表です。Sketch はとても良いけど、使う人が中身を見れないことがあります。また、Storyboard をそのまま作ることができない。それを解決してくれる Sympli というツールがあるよ!というお話でした。

sympli.io

ストレッチタイム

ここで体をほぐすためのストレッチタイムが入りました。さすがは FiNC さんですね!(写真は自粛)

実装とアプリ開発と独学でiOSアプリ開発と向き合うこと

fumiyasacさんによる発表です。fumiyasacさんは30歳から独学でアプリ開発を始めたそうです。

コードレビューがない孤独な環境でバッドノウハウを実装してしまうこともありましたが、Qiitaに記事を投稿したり、勉強会に参加することで壁を乗り越えてきたそうです。 アプリ開発を勉強する際に読んだ参考書なども紹介されていました。

Notification in iOS10

Tachibana Kaoru さんによる Notification の発表!ちなみに、Tachibanaさんは来月からフリーランスになられるそうです!🎉

iOS 10 からは Notification の配信状況を簡単にハンドリングできるようになりました。例えば、「Notificationがまだ発火してない」「発火したけどユーザがタップしてない」、などを取得できます。また、Notificationにidを振ることにより、あとから編集・削除ができるそうです。

iOS 10 で Notification はだいぶ進化しましたね〜

[iOS 10] Programmatically creating a custom Sticker application

akio0911 さんによる発表です。iOS 10から作れるようになった Sticker についてのお話でした。

個人的にまず驚いたのは、いよいよ「アプリ本体が無いアプリ」が登場する、という点でした。

MSStickerBrowserController などのクラス構造もわかりやすく解説されていました。Sticker を選択する画面は CollectionView を使ってカスタマイズすることもできるそうです。

さいごに

最初の potatotips 開催からそろそろ3年経つんですな。

時が経つのは早いものです😌

WWDC16情報共有会@Fablic で発表してきたよ

6/27(月)、Fablicさんで開催されたWWDC16情報共有会にて「User Notification Framework」の話をしてきました。

fablic.connpass.com

持ち時間5分ということもあり、簡単な概要、従来のAPIとの違い、そして基本的な使い方のみざっと紹介しました。

(今回からSpeakerDeckに乗り換えたんですが、かなり良い感じ)

より高度な画像付きプッシュなどについては、WWDCのビデオを見ることをお勧めします。


f:id:koogawa:20160703112627p:plain

Fabricさんにお邪魔するのは初めてでしたが、とてもオシャレなオフィスでした。

f:id:koogawa:20160703112718p:plain

ピザも美味しかったです!ごちそうさまでした🍕

リンク

#yidev 第24回横浜iPhone勉強会に参加してきたよ

f:id:koogawa:20160702235648p:plain

今日は第24回横浜iPhone勉強会に参加してきました。

https://atnd.org/events/78243atnd.org

今回も発表枠はあっという間に埋まり、参加者枠もキャンセル待ちが出るほどの盛況ぶりでした。

参加者のアイコンを並べたスライドが今回も大活躍😃

f:id:koogawa:20160702235824p:plain

また、岸川さんより try! Swift の参加証を頂きました!ありがとうございます。

f:id:koogawa:20160702235910p:plain

当日のツイートはTogetterにまとめています。

***

そんなわけで以下、発表内容の簡単なメモになります。(発表者の皆さま、間違い等あればご指摘ください)

Xcode 8 + Server

noriri_ さんによる発表です。Xcode 8でパワーアップしたServerについてのお話でした。

  • Xcode Server
    • メリット
      • バイスでテストできる
      • Betaをテストできる
      • パフォーマンスがよい
    • デメリット
      • セットアップが難しい(.travis.yml みたいに簡単にいかない)
      • 他のサービスとの連携がしづらい
      • Github の clone にめっちゃ時間かかる
  • Server 5.2 + Xcode 8 でいろいろ改善されている
    • 好きなユーザでビルドできるようになった

CoreData 大容量データ マイグレーション

yaso_san さんによる発表です。大量にメモリを消費するCoreDataのマイグレーションについて、その理由と改善策を解説されていました。Instruments を使ったデモがわかりやすかったです。

  • CoreDataのマイグレーションは大量にメモリを消費する
  • マイグレーションの仕組み
    • Lightwight Migration - おまかせ
    • Custom Migration - 細かくカスタマイズ可
    • の2種類が存在する
  • Custom Migration
    • Stage 1: オブジェクトをSourceからDestinationに新しい形式でコピー
    • Stage 2: 関連をセット
    • Stage 3: 検証
  • 何故メモリを消費するのか?
    • データを引き継ぐために全てのオブジェクトをメモリに載せてるから
  • マイグレーション分割の壁
      1. 分割する数だけMapping Modelが必要
      1. SourceとDestinationのオブジェクトの結びつきは分割すると引き継げない
      1. 分割した数だけ時間がかかる
  • マイグレーション分割の改善
      1. オブジェクトに一意の値を持たせる
      1. グループ分けできる値を持たせて1つのエンティティ内で分割する
      1. Mapping Modelをコードで分ける
      1. 関連先のエンティティのマイグレーション順を前にする
  • まとめ
    • メモリと時間はトレードオフ
    • エンティティ毎のデータ量によって分け方をかえる
    • 処理の順番を決めて無駄な関連付けをしない
    • 必要のないデータは引き継がない

Xcode 8 移行に備える

田畑浩平 さんによる発表。みんな気になる Swift 2.3 / 3 移行のお話でした。

  • ATS必須化
    • すべての通信においてHTTPSが要求される
    • それ以外で使う場合は設定が必要
  • Swift 2.3/3 への移行
    • Swift 3 : Xcode 8 がメインでサポート
    • Swift 2.3 : Swift 3 への移行準備ができていない開発者が最新のSDKを使うためのもの
  • 移行ToDo
    • まずはSwift 2.3移行
    • Swift 2.3でエラーを吐くライブラリにはPR
    • 2.3 での動作が担保されたら3への移行を試す
    • Xcodeにバグが有る場合はApple Bug Reportからバグ報告
    • 使用しているライブラリがすべて3をサポートした時点でSwift 3へ移行

マルチプラットフォーム展開アプリに音声インタラクションを追加するお話!

k2-ikeda さんによる発表です。SiriKIt、OK Google、コルタナのデモもありましたよ!

  • SiriKit
    • iOS 10以降
    • 日本語が使える
    • 特定ドメインへの対応アプリが作れる
    • 対応シーンは限定的
  • OK Google
    • アラーム、電話をかける、フィットネス、乗車予約などが可能
    • 日本語が使える、と書いてあるが実際は不安定
  • コルタナ(Windows
    • Windows 10〜
    • 応答パターン用のxmlを書かないといけない
  • まとめ
    • 最近の環境であればどのプラットフォームも対応している
    • SiriKit対応は他のプラットフォームのことはあまり気にしないで行えばよいのでは
    • 対応するドメイン領域もそうだけど、「どのプラットフォーム版のアプリでも同様のUXを提供」みたいなのが要件にのってくるアプリには特に日本語環境では向かない

React-native について!

yuumi3 さんによる発表。Facebookが公開している React-native のお話でした。

  • React-native
  • React.js とは
    • *.js 系は色々出てきたけど、これが勝者!
    • シンプルなプログラミングモデルと性能を両立
    • メンテナンス性の高いコードが書ける
  • ES2015(ES6)
    • class 構文が導入された!
    • すべてのブラウザがサポートしているわけではない

iOS 10 Extensions ざっくり確認!

tmokita さんによる発表です。iOS 10で追加された Extensions について、みんなでおさらいしていくスタイルがとても良い感じでした。

  • Map Extensions
    • 使おうとしたけどできなかった
  • Extensions ざっくり確認
    • Xcode 8 増えたもの
      • Broadcast UI
      • Broadcast Upload
      • Call Directory
      • Intents
      • Intents UI
      • Message
      • Notification Content
      • Notification Service
      • Sticker Pack

なお、Map Extensions については次の順番で調べていけばよいのでは、と id:KishikawaKatsumi さんがおっしゃっていました。

さいごに

id:niwatako さんがとても良いことを言っていました。

これは本当に同感で、yidevは発表者でなくとも、勉強会が終わった後に不思議な充実感が得られるのです。

yidev には発表中にも普通に参加者から質問が投げられ、そのままディスカッションが始まる文化があります。これは他の勉強会ではあまり見られない光景だと思っています。きっと「講習会ではないですからね :D」の文化が根付いているんでしょうね😃

yidev、次回も楽しみです!