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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Muukii
May 15, 2018
Programming
2.8k
12
Share
快適なUIを持つアプリを作るために できること
Muukii
May 15, 2018
More Decks by Muukii
See All by Muukii
Problem Solving from the Abstraction Layer
muukii0803
1
60
Pairs iOSとトレンドの技術
muukii0803
0
1k
Thoughts about build flow
muukii0803
2
350
スマホアプリ開発で大切なこと
muukii0803
3
190
エンジニアとして働くために
muukii0803
0
210
Q. Textureは部分的に導入できますか?
muukii0803
3
2.6k
安定したチャットを実現するための アプリとAPI設計
muukii0803
17
8.5k
iOS エンジニアが考える Webアプリ開発
muukii0803
3
520
AutoLayout以外の選択肢
muukii0803
13
5.4k
Other Decks in Programming
See All in Programming
AI時代の脳疲弊と向き合う ~言語学としてのPHP~
sakuraikotone
1
1.8k
まかせられるPM・まかせられないPM / DevTech GUILD Meetup
yusukemukoyama
0
110
見せてもらおうか、 OpenSearchの性能とやらを!
shunta27
1
180
Migration to Signals, Signal Forms, Resource API, and NgRx Signal Store @Angular Days 03/2026 Munich
manfredsteyer
PRO
0
240
年間50登壇、単著出版、雑誌寄稿、Podcast出演、YouTube、CM、カンファレンス主催……全部やってみたので面白さ等を比較してみよう / I’ve tried them all, so let’s compare how interesting they are.
nrslib
4
720
実践CRDT
tamadeveloper
0
370
Don't Prompt Harder, Structure Better
kitasuke
0
450
PCOVから学ぶコードカバレッジ #phpcon_odawara
o0h
PRO
0
230
AIエージェントで業務改善してみた
taku271
0
500
LM Linkで(非力な!)ノートPCでローカルLLM
seosoft
0
410
forteeの改修から振り返るPHPerKaigi 2026
muno92
PRO
3
240
瑠璃の宝石に学ぶ技術の声の聴き方 / 【劇場版】アニメから得た学びを発表会2026 #エンジニアニメ
mazrean
0
180
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Scaling GitHub
holman
464
140k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.2k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
The SEO identity crisis: Don't let AI make you average
varn
0
440
Building Adaptive Systems
keathley
44
3k
Discover your Explorer Soul
emna__ayadi
2
1.1k
Unsuck your backbone
ammeep
672
58k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
160
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
450
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
200
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
120
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