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
通信処理を差し替えてみた話
Search
Tatsuya Tanaka
February 15, 2017
Technology
5
2.4k
通信処理を差し替えてみた話
URLProtocolとMethod Swizzlingの話
#potatotips 37
Tatsuya Tanaka
February 15, 2017
Tweet
Share
More Decks by Tatsuya Tanaka
See All by Tatsuya Tanaka
iPhoneのセンサー情報をmacOSアプリでリアルタイム活用するための技術
tattn
1
620
Better use of SwiftUI
tattn
0
430
Swift Concurrencyによる安全で快適な非同期処理
tattn
2
1.3k
iOSアプリの技術選択2022
tattn
7
3.8k
Widget Suggestions 対応と ヤフーの新OS対応
tattn
1
1.3k
WidgetKitで良い体験を作るには / Good experience with WidgetKit
tattn
2
1.6k
既存アプリにSwiftUIをどう組み込んでいくか
tattn
8
2.4k
iOS 14からのアプリ内課金
tattn
5
2.9k
iOS 14の位置情報系アップデート
tattn
0
22k
Other Decks in Technology
See All in Technology
A2Aのクライアントを自作する
rynsuke
1
190
強化されたAmazon Location Serviceによる新機能と開発者体験
dayjournal
3
220
~宇宙最速~2025年AWS Summit レポート
satodesu
1
1.9k
より良いプロダクトの開発を目指して - 情報を中心としたプロダクト開発 #phpcon #phpcon2025
bengo4com
1
3.1k
OpenHands🤲にContributeしてみた
kotauchisunsun
1
460
BigQuery Remote FunctionでLooker Studioをインタラクティブ化
cuebic9bic
3
320
Observability в PHP без боли. Олег Мифле, тимлид Altenar
lamodatech
0
360
AIの最新技術&テーマをつまんで紹介&フリートークするシリーズ #1 量子機械学習の入門
tkhresk
0
140
Node-REDのFunctionノードでMCPサーバーの実装を試してみた / Node-RED × MCP 勉強会 vol.1
you
PRO
0
120
Agentic Workflowという選択肢を考える
tkikuchi1002
1
540
25分で解説する「最小権限の原則」を実現するための AWS「ポリシー」大全 / 20250625-aws-summit-aws-policy
opelab
9
1.2k
Clineを含めたAIエージェントを 大規模組織に導入し、投資対効果を考える / Introducing AI agents into your organization
i35_267
4
1.6k
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
5.6k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Embracing the Ebb and Flow
colly
86
4.7k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
Navigating Team Friction
lara
187
15k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Side Projects
sachag
455
42k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Adopting Sorbet at Scale
ufuk
77
9.4k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
Transcript
௨৴ॲཧΛࠩ͠ସ͑ͯΈͨ
ࣗݾհ • ాதୡ (@tattn) • Ϡϑʔͷ2016৽ଔ
Qiitaͱ͔Twitterͱ͔ͬͯ·͢ • ։ൃ͕രʹͳΔSwift༻XcodeϓϥάΠϯΛ·ͱΊͯΈͨ • ͏ͱख์ͤͳ͘ͳΔSwift Extensionू (Swift3൛) @tanakasan2525
APIͷϢχοτςετͲ͏ͯ͠·͢ ͔ʁ
DIʁ ϥΠϒϥϦʁ
MockingjayศརͰ͢ΑͶ
Mockingjay https://github.com/kylef/Mockingjay let body = [ "user": "Kyle" ] stub(uri("/{user}/{repository}"),
json(body))
Ͳ͏͍͏ΈͰಈ͍ͯΔΜͩΖ͏ !
ௐͯΈΔͱ
URLProtocolͱMethod Swizzling Λͬͯ௨৴ॲཧΛࠩ͠ସ͍͑ͯ·͠ ͨ
URLProtocol https://developer.apple.com/reference/foundation/urlprotocol αϙʔτ֎ͷϓϩτίϧͰ௨৴͢Δ߹ ϦΫΤετΛಠࣗͷํ๏Ͱॲཧ͢Δ࣌ʹ͏Ϋϥεɻ
Mock༻ͷURLProtocol public class MockURLProtocol: URLProtocol { override open func startLoading()
{ let jsonString = "{\"mock\": \"data\"}" let json = jsonString.data(using: .utf8)! self.client?.urlProtocol(self, didLoad: json) self.client?.urlProtocolDidFinishLoading(self) } // ͦͷଞϝιουলུ }
Method SwizzlingͰϞοΫ༻ͷURLProtocol ʹࠩ͠ସ͑ public extension URLSessionConfiguration { public class func
setup() { let `default` = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.default)) let swizzled = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.mock)) method_exchangeImplementations(`default`, swizzled) } private dynamic class var mock: URLSessionConfiguration { let configuration = self.mock configuration.protocolClasses?.insert(MockURLProtocol.self, at: 0) URLProtocol.registerClass(MockURLProtocol.self) return configuration } }
ֶ͔ͤͬ͘ΜͩͷͰϥΠϒϥϦԽ͠· ͨ͠ !
Replacer https://github.com/tattn/Replacer ௨৴ͷελϒԽMethod SwizzlingΛαϙʔτ͢ΔϥΠϒϥϦ
Method ChainͰΦϓγϣϯΛઃఆ͠·͢ self.urlStub .url("echo.jsontest.com/[a-z]+/.*") .httpMethod(.post) .json(["test": "data"]) .delay(1.5)
QuickͱAlamofireͰͷελϒԽ describe("Quick compatibility test") { it("returns mock data") { let
url = "http://echo.jsontest.com/key/value/one/two" var json: [String: String]? Alamofire.request(url, method: .post).responseJSON { response in json = response.result.value as? [String: String] } expect(json?["test"]).toEventually(equal("data")) } }
ओͳػೳ • ௨৴ͷελϒԽ • XCTestҎ֎ (Host ApplicationؚΉ) Ͱ༻Մೳ • Method
Swizzlingͷαϙʔτػೳ ͳͲͰ͢ɻ
ྑ͔ͬͨΒͬͯΈ͍ͯͩ͘͞ ! (ʁʁ)ʻ ܅⭐͕େ͖ͳϑϨϯζͳΜͩͶʂ
͋ɺͦ͏͍͑ɺɺɺ
࡞͍ͬͯΔ࣌ʹSwiftͷόάʹؾ͕͖·ͨ͠ ڥ: Xcode 8.2, Swift 3.0.2
άϩʔόϧఆٛ͞ΕͨؔʹϞδϡʔϧ໊Λ͚ Δͱɺ@discardableResult͕ਖ਼ৗʹಈ࡞͠ͳ͍
ઌఔௐͯΈΔͱɺमਖ਼͞ΕͨΈ͍ͨͰ͢ ! https://bugs.swift.org/browse/SR-3665 Fix @discardableResult when invoking function with explicit
namespace #7201
SwiftͷਐԽɾվળࢭ ·Βͳ͍Ͱ͢Ͷʂ !
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝ ·ͨ͠ʂ