Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
快適なUIを持つアプリを作るために できること
Search
Muukii
May 15, 2018
Programming
12
2.6k
快適なUIを持つアプリを作るために できること
Muukii
May 15, 2018
Tweet
Share
More Decks by Muukii
See All by Muukii
Pairs iOSとトレンドの技術
muukii0803
0
890
Thoughts about build flow
muukii0803
2
280
スマホアプリ開発で大切なこと
muukii0803
3
140
エンジニアとして働くために
muukii0803
0
160
Q. Textureは部分的に導入できますか?
muukii0803
3
2.3k
安定したチャットを実現するための アプリとAPI設計
muukii0803
17
7.8k
iOS エンジニアが考える Webアプリ開発
muukii0803
3
470
AutoLayout以外の選択肢
muukii0803
13
5.2k
Decodable - Pairs Taiwan
muukii0803
1
910
Other Decks in Programming
See All in Programming
新宿駅構内を三人称視点で探索してみる
satoshi7190
2
110
AWS Organizations で実現する、 マルチ AWS アカウントのルートユーザー管理からの脱却
atpons
0
150
DROBEの生成AI活用事例 with AWS
ippey
0
140
React 19アップデートのために必要なこと
uhyo
5
730
さいきょうのレイヤードアーキテクチャについて考えてみた
yahiru
3
760
Writing documentation can be fun with plugin system
okuramasafumi
0
120
pylint custom ruleで始めるレビュー自動化
shogoujiie
0
130
WebDriver BiDiとは何なのか
yotahada3
1
150
Pulsar2 を雰囲気で使ってみよう
anoken
0
240
ARA Ansible for the teams
kksat
0
160
Introduction to kotlinx.rpc
arawn
0
740
2024年のWebフロントエンドのふりかえりと2025年
sakito
3
260
Featured
See All Featured
Unsuck your backbone
ammeep
669
57k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
420
Building Applications with DynamoDB
mza
93
6.2k
GraphQLとの向き合い方2022年版
quramy
44
13k
We Have a Design System, Now What?
morganepeng
51
7.4k
Optimizing for Happiness
mojombo
376
70k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Transcript
շదͳUIΛ࣋ͭΞϓϦΛ࡞ΔͨΊʹ Ͱ͖Δ͜ͱ Muukii Pairs Global Team eureka, Inc.
About Me • Muukii <Hiroshi Kimura> • iOS Engineer at
eureka, Inc. • Pairs Global Team • GitHub : @muukii • https://muukii.me ☕ ⌚
None
1BJSTʹ͍ͭͯ !4
4PVUI,PSFB Japan Taiwan No.1 2017 release No.1 !5 1BJSTʹ͍ͭͯ ల։ࠃ
̐ͭͷϓϥοτϑΥʔϜ CONFIDENTIAL INFORMATION: Not for Public Distribution - Do Not Copy
None
Agenda • Pairs Global iOS νʔϜɾϓϩδΣΫτͱͯ͠ • շదͳUIΛ࣋ͭΞϓϦΛ࡞ΔͨΊʹ͍ͬͯΔ͜ͱ • ߈Ί
- Improve • ߴʹಈ࡞͢ΔUI ɾ ҆ఆͨ͠UI • कΓ - Maintain • ߈ΊʹΑ࣮ͬͯݱͨ͠UIͷ࣭Λܧଓͤ͞Δ
Improve
ࢦ͖࣭͢ • Ϣʔβʔʹͱͬͯͷී௨Facebook, InstagramϨϕϧͷಈ࡞ • ൴ΒΞϓϦͱ͍͏Ϟϊͱͯ͠ͷࠜຊతͳج४Λ࡞Γ্͍͛ͯΔ • εϜʔζͳ͍৺ • εΫϩʔϧ࣌ɾը໘ભҠ࣌ͷύϑΥʔϚϯε
• ঢ়ଶɾใΛ҆ఆతʹਖ਼͘͠දࣔ
UI࣮ͷΞϓϩʔν • InterfaceBuilderҰ༻ͤͣίʔυϨΠΞτ • AutoLayoutEasyPeasyͱ͍͏ϥΠϒϥϦΛ༻த • UIͷಈ࡞ύϑΥʔϚϯεʹ͓͚ΔϘτϧωοΫAutoLayoutؔ࿈Ͱൃੜ͢Δ͜ͱ͋Δ • TextureGroup/TextureΛ༻ (Pinterest͕։ൃ͠ɺ൴ΒͷϓϩμΫτͰશ໘తʹ༻͍ͯ͠Δ)
• పఈతʹඇಉظॲཧԽ͠ɺUI͕ඇৗʹߴʹͳΔେ͖ͳϥΠϒϥϦ • AutoLayoutͱͦͷସखஈʹ͍ͭͯൃදࢿྉ͕͋ΔͷͰΑ͚Ε͝ཡ͍ͩ͘͞ https://speakerdeck.com/muukii0803/autolayoutyi-wai-falsexuan-ze-zhi
ঢ়ଶΛਖ਼͘͠දࣔ͢Δ • UIͷಈ࡞ॏཁ͕ͩɺݱࡏͷঢ়ଶΛਖ਼͘͠දࣔ͢Δ͜ͱॏཁ • 1ճͰҰॠͰؒҧͬͨঢ়ଶΛදࣔ͢ΕϢʔβʔࠞཚ͢Δ • Fluxͷ֓೦Λར༻͢Δ͜ͱͰෳࡶͳঢ়ଶΛ͑ͯViewʹදࣔ͢Δ͜ͱ͕Ͱ͖Δ • ͦΕͱಉ࣌ʹϝϯςφϯεੑͷ্ظͰ͖Δ
࣮ࡍͷΞϓϦͷಈ͖ • on iPhone7 • ࣸਅදࣔͤͣɺϓϩϑΟʔϧใμϛʔʹࠩ͠ସ͍͑ͯ·͢ɻ • ΄ͱΜͲͷಈ࡞ʹ͓͍ͯ60fpsʹ͍ۙΒ͔͕࣮͞ݱͰ͖͍ͯΔɻ
Maintain
UIͷෆ۩߹ͱݺΔͷ • ظ௨Γಈ͍͍ͯͳ͍ (͜Εવ) • ॲཧʹ͕͔͔࣌ؒΓUI͕ݻ·ͬͯ͠·͏ • UI͕ॠ࣌ʹԿ͔ΓସΘͬͯ͠·͏Α͏ͳνϥπΩ • σβΠϯ่Ε
• ࢹೝੑɾใઃܭΛߟ͑ͯͷσβΠϯͰ͋ΔͨΊɺ่Ε͍ͯΕUIͱͯ͠ຊདྷͷػೳΛఏڙͰ͖ͯ ͍ͳ͍ͱݴ͑Δ • ը૾ͷΞεϖΫτൺ͕ؒҧ͍ͬͯΔ • Not ϐΫηϧύʔϑΣΫτ • ΞΠίϯͷҰ෦͕͚ܽͯදࣔ͞Ε͍ͯΔ
ෆ۩߹Λى͜͞ͳ͍ͨΊʹ • ෆ۩߹ώϡʔϚϯΤϥʔʹΑͬͯى͜Δ͜ͱ͋Δ • ͦͷதʹʮಈ࡞֬ೝ͕໘ʯʹΑΔͷؚ·Εͯ͘Δ • ʮಈ࡞֬ೝͷͨΊʹ४උ͢Δ͜ͱ͕ଟ͍ɻʯͱ͔ • ؆୯ʹಈ࡞֬ೝΛߦ͑ΔΑ͏ʹ͢Δ͜ͱͰෆ۩߹ΛݮΒͤΔ •
खؒͷഉআ • QAͷਓḿΔ
։ൃऀϝχϡʔ ΞϓϦαΠυ • ΞϓϦىಈ࣌ʹΞϓϦͷಈ࡞ํ๏ڥΛબ͢Δը໘Λදࣔ
None
ଓ͢ΔαʔόʔΛબ • ຊ൪αʔόʔ ؖࠃɾ • ։ൃ༻αʔόʔ ؖࠃɾ • ϩʔΧϧ (localhost:8000ͳͲ)
• ϚϧνϩάΠϯՄೳͳΞϓϦઃܭʹ͍ͯ͠ΔͨΊɺෳϢʔβʔͷϩ άΠϯঢ়ଶΛอ࣋Մೳ & ϥϯλΠϜͰΓସ͑Մೳ • ڥมߋͷͨͼʹϏϧυ͢͠ඞཁͳ͠
ը໘αΠζͷมߋ • Application.windowͷαΠζΛڧҾʹมߋ͢Δػೳ • શ࠶ݱͰ͖ͳ͍͕ɺ5.5inchͷσόΠεΛ༻͠ͳ͕Β4inch ͷը໘ͰUIΛ֬ೝ͢Δ͜ͱ͕Ͱ͖Δ • খ͍͞ը໘Ͱจࣈ͕Ε͍ͯͨΓɺ σβΠϯ͕ཚΕ͍ͯΔ͜ͱʹؾ͚ͮΔ
Ϗϧυʹؔ͢Δใ • ͕֬ೝ͞Εͨ߹ʹใࠂΛߦ͍͘͢͢ΔͨΊ • Ϗϧυ࣌ʹJSONΛ࡞ΓɺΞϓϦʹόϯυϧ͢Δख๏Λͱ͍ͬͯΔ Script: https://gist.github.com/muukii/cc655b0cf0d7986421725a5493c7f3d8
։ൃऀϝχϡʔ ϏδωεϩδοΫαΠυ
• ΞϓϦΛར༻͠ͳ͕ΒαʔόʔͷϏδωεϩδοΫΛݺͼग़͢ (։ൃڥͷΈ) • ϢʔβʔΛԡ͠ -> Ϣʔβʔ(૬ख)ʹؔ͢ΔϝχϡʔΛදࣔ • ࣗʹʮ͍͍ͶʂʯΛૹ৴ •
ࣗʹϝοηʔδΛૹ৴ • σόΠεΛγΣΠΫ -> Ϣʔβʔ(ࣗ)ʹؔ͢ΔϝχϡʔΛදࣔ • ձһঢ়ଶͷมߋ (ແྉɾ༗ྉ) • ͦͷଞ ঢ়ଶมߋ ։ൃऀϝχϡʔ ϏδωεϩδοΫαΠυ
GitHub PRʹ.appΛΞοϓϩʔυ • GitHubʹPR͕࡞͞ΕΔͱCI͕γϛϡϨʔλ༻ͷappΛϏϧυ • PRʹappϑΝΠϧͷμϯϩʔυϦϯΫ͕షΓ͚ΒΕΔ • μϯϩʔυͨ͠appϑΝΠϧγϛϡϨʔλʹυϥοά&υϩοϓͰΠϯετʔϧՄೳ • ίʔυϨϏϡʔͰΘ͔Βͳ͍࣮ࡍͷಈ࡞ݟͨΛ֬ೝ͢Δ·Ͱͷૢ࡞͕ॖͰ͖Δ
• γϛϡϨʔλෳىಈՄೳʹͳ͍ͬͯΔͷͰσόΠε͝ͱͷ֬ೝ؆୯ʹ • ؔ࿈هࣄ : https://bit.ly/2IhHOgl • CIϏϧυΛ͘ߦ͍͍ͨͷͰࣾͷmac proͰಈ͔͍ͯ͠Δ • JenkinsͰΑ͔͚ͬͨͲɺڵຯຊҐͰ࡞ͬͨSwiftͷCIΛ༻த… • https://github.com/eure/tower • (Jenkins, Travis, Bitrise, CircleCIͱ͔Ͱ͍͍ͱࢥ͏)
GitHub PRʹ.appΛΞοϓϩʔυ appϑΝΠϧͷμϯϩʔυϦϯΫ
γϛϡϨʔλ༻appϑΝΠϧΛ࡞Δ lane :simulator_build do base_path = `xcodebuild -workspace ../pairs-global.xcworkspace -scheme
Pairs - arch x86_64 -sdk iphonesimulator -configuration Debug -showBuildSettings | grep - m 1 "CONFIGURATION_BUILD_DIR" | grep -oEi "\/.*"`.chomp() result = xcbuild( workspace: 'pairs-global.xcworkspace', scheme: 'Pairs', xcargs: '-arch x86_64 -sdk iphonesimulator -configuration Debug' ) File.join(base_path, "Pairs.app") end FastlaneΛͬͨྫ ϏϧυΛߦ͍ɺ.appͷύε͕ฦ٫͞ΕΔlane
GitHubͷPRΛ୳͢Query query FindPullRequest( $owner: String!, $name: String!, $branch: String!) {
repository(owner:$owner, name:$name) { pullRequests(first: 1, headRefName:$branch) { nodes { id, number }, totalCount, } } } { "owner" : "eure", "name" : "pairs-gl-ios", "branch" : "#{branch_name}" } GitHub API v4 GraphQL
ൃੜ͍ͯ͠Δෆ۩߹ʹؾͮͨ͘Ίʹ • ΞϓϦΛϦϦʔε͢Δ·Ͱʹग़དྷΔ͜ͱͨ͘͞Μ͋Δ͕ɺͦΕͰෆ۩߹ΛؚΜͩ··ϦϦʔε ͞Εͯ͠·͏͜ͱ͋Δ • ϦϦʔεޙɺϢʔβʔͷखݩͰൃੜ͍ͯ͠ΔʹϢʔβʔ͔Βͷ͓͍߹ΘͤͰͳ͘ɺͪ͜Β ͔ΒݕͰ͖ΔΑ͏ʹ͓͕ͯ͘͠ॏཁ
CrashlyticsʹNon-Fatal-Errorͱͯ͠ΫϥογϡܥҎ֎ͷΤ ϥʔΛૹ৴͢Δ func log(error: Error) { Crashlytics.sharedInstance().recordError(error, withAdditionalUserInfo: nil) }
CrashlyticsʹNon-Fatal-Errorͱͯ͠ΠϕϯτΛૹ৴͢Δίʔυྫ CrashlyticsࣗಈͰΫϥογϡϩάΛૹ৴͢ΔSDK͕ͩɺ։ൃऀ͕ࢦఆͨ͠ΠϕϯτΛΫϦςΟΧϧ Ͱͳ͍͕ͷ͋ΔΤϥʔ(Non-Fatal-Error)ͱͯ͠ૹ৴͢Δػೳ͍࣋ͬͯΔ
՝ۚ͠ͳ͚Εϝοηʔδͷ ༰ݟΕͳ͍ɻ ϝοηʔδΛ։෧ϘλϯΛԡ ͢͜ͱ͕Ͱ͖Δ ։෧ϘλϯΛԡ͢ͱɺ՝ۚը ໘͕දࣔ͞ΕΔ(Ϟʔμϧ) ՝ۚͯ͠՝ۚը໘Λด͡Δͱ ϝοηʔδ͕දࣔ͞ΕΔ (σʔλͷ࠶ಡΈࠐΈ) ঢ়ଶ
: ແྉձһ ঢ়ଶ : ༗ྉձһ
ԡͤͳ͍ͣͷϘλϯ͕ԡ͞Εͨ͜ͱΛݕ͢Δ let error = ..."ϝοηʔδ։෧Ͱ͖͍ͯΔ͔ͣͩΒ Ϙλϯԡͤͳ͍ͣ" log(error: error) ϘλϯΛλοϓ͞ΕͨλΠϛϯάͰঢ়ଶΛ֬ೝͯ͠ΤϥʔΛૹ৴͓ͯ͘͠ ྫ͑ɺʮ༗ྉձһͷϢʔβʔ͕։෧ϘλϯΛԡͯ͠͠·ͬͨʯ
͔͠͠ɺຊདྷϝοηʔδͷ༰͕දࣔ͞Ε͍ͯΔͣͳͷͰɺϘλϯԡͤͳ͍ͣɻ ErrorΦϒδΣΫτCustomNSError ͱ, LocalizedErrorΛ࣮͢Δͱྑ͍
None
ϢʔβʔͷखݩͰൃੜ͍ͯ͠Δྫ֎ʹؾ͚ͮΔΑ͏ʹ ͳΔ • UIςετΛॻ͘ͷΞϦ͕ͩɺͦΕͰϢʔβʔͷखݩͰԿ͕ى͖Δ͔Θ͔Βͳ͍ͷ͕ΞϓϦ։ ൃͷޣຯ • UIςετͰݕͰ͖ͳ͍ͷ͋Δ • γφϦΦΛࣗͨͪͰ࡞͍ͬͯΔ͔Β •
ϥϯλΠϜͰϢʔβʔ͕ߦͳͬͨಈ࡞͕༷͔Β֎Ε͍ͯͳ͍͔ΛνΣοΫ͢ΔΑ͏ʹ͓ͯ͘͠ͱ ྑ͍ • ݕॲཧ͕େ͖ͳෛՙʹͳΒͳ͍Α͏ʹؾΛ͚ͭΔ
ϢʔβʔͷखݩͰൃੜ͍ͯ͠Δྫ֎ʹؾ͚ͮΔΑ͏ʹ ͳΔ • ҆ఆͨ͠UIΛ࣮ݱ͢ΔͨΊʹFluxͳͲͷ࣮ઃܭͰՄೳ • ͔͠͠ɺͦΕͰෆ۩߹ൃੜ͢Δ • ϦϞʔτͰྫ֎ΛϩΪϯά͢Δ͜ͱͰؾ͚ͮΔ • ಈ࡞ݕূ͕࿙Εͯෆ۩߹ݕ·Ͱͷ͕࣌ؒ͘Ͱ͖Δ
• ෆ۩߹͕ൃੜ͢Δͷํͷͳ͍͜ͱɻͦͷΘΓૣ͘ؾ͖ͮɺਝʹमਖ਼Ͱ͖Δମ੍Λ࡞ͬ ͓ͯ͘ɻ
ෆ۩߹Λత֬ʹमਖ਼͢ΔͨΊʹ • ྫ֎ΠϕϯτΛCrashlyticsʹૹ৴͢Δ͜ͱʹΑΓɺ͕ൃੜ͍ͯ͠Δ͜ͱʹؾ͚ͮΔΑ͏ʹ ͳͬͨ • ͦͷ࣍ؾ͍ͨΛత֬ʹमਖ਼͢ΔͨΊʹɺͳ͕ͥൃੜ͍ͯ͠Δͷ͔ɺͲͷΑ͏ʹͯ͠ ͕ى͖ͨͷ͔ΛΔඞཁ͕͋Δ
CrashlyticsʹϩάΛૹ৴͓ͯ͘͠ • Crashlyticsʹίϯιʔϧϩάʹදࣔ͢ΔΑ͏ͳϩάΛૹ৴͢Δػೳ͕͋ΓɺCrashΠϕϯτ Non-Fatal-ErrorΠϕϯτͱඥ͚ͮͯ͘ΕΔ func log(string: String) { CLSLogv("%@", getVaList([string]))
} CrashlyticsʹϩάΛૹ৴͢Δίʔυྫ
None
ϩάͱͯ͠ૹ৴͍ͯ͠Δ༰ • શͯͷը໘ભҠΛࣗಈͰϩΪϯά • ViewControllerͷϥΠϑαΠΫϧΛτϥοΩϯά • https://github.com/muukii/ApplicationMonitor • Fluxϕʔεͷ࣮ͳͷͰݺͼग़͞ΕͨΞΫγϣϯΛࣗಈͰϩΪϯά •
ͦͷଞ ࣮ߦ͞ΕͨॲཧͷதͰॏཁͳͷ͕͋ΕadhocͰϩάΛࠐΉ
ෆ۩߹ൃੜʹࢸΔ·Ͱͷߦಈ͕ಡΊΔΑ͏ʹͳΔ • Ϣʔβʔ͕ߦͳͬͨૢ࡞Λϩάͱͯ͢͜͠ͱ͕Ͱ͖Εɺ ։ൃऀͷखݩͰ࠶ݱͰ͖ɺૉૣ͘मਖ਼Ͱ͖ΔΑ͏ʹͳΔՄೳੑ͕ߴ·Δ • ࠶ݱ͕͔ͬͨ͠Γใ͕Γͳ͚Εɺ৽͘͠ϩάΛऔΕΔΑ͏ʹमਖ਼͠ɺ͙͢ʹϦϦʔεΛߦ ͏ • ख͕͔Γ͕ͳ͍ෆ۩߹΄Ͳਏ͍ͷͳ͍
Thank you