: WWDC 2020, . , , â - , . , , - WWDC
ããªãã®ã»ãšãã©ã¯ãããããæ©èœã®å€ããHTTPãä»ãããµãŒããŒãšã®éä¿¡ã«äŸåããŠããã¢ããªã±ãŒã·ã§ã³ã§äœæ¥ããããçŸåšäœæ¥ããŠããŸããç©äºãæåŸ ã©ããã«æ©èœããªãå ŽåããŸãã¯ãŸã æ £ããŠããªãã³ãŒãã®é åãçè§£ãããå Žåã¯ãã¢ããªã±ãŒã·ã§ã³ãšãµãŒããŒã®éã§è¡ãããHTTPèŠæ±ã確èªãããšåœ¹ç«ã€ããšããããããŸããã©ã®ãããªãªã¯ãšã¹ãããããŸãããïŒãµãŒããŒã¯æ£ç¢ºã«äœãéä¿¡ããŠããŸããïŒãã®ããã«ãããªãã¯ããããã®ãããªããŒã«ã䜿çšãã£ãŒã«ãºãããã·ãŸãã¯Wiresharkã®ãã
ãã ãããããã®ããŒã«ã¯ã䜿çšãç¹ã«ã»ããã¢ãããéåžžã«é£ããããšããããããŸããç¬èªã®SSLèšŒææžãèšå®ããããã€ã¹ã«ãããä¿¡é Œãããããã«å€ãã®éèŠãªæé ãå®è¡ããå¿ èŠãããå ŽåããããŸãããŸããã¢ããªã±ãŒã·ã§ã³ãçè§£ããå¿ èŠããªãå¯èœæ§ã®ããå€ãã®æ å ±ã衚瀺ãããŸããåæã«ãã¢ããªã±ãŒã·ã§ã³ã§äœãèµ·ãã£ãŠããã®ãããããã³ã°ããããšã¯å°é£ã§ãããã®äœæ¥ã®ã»ãšãã©ãå®è¡ã§ããã»ããã¢ããã«ãããæéãå€§å¹ ã«å°ãªããã¢ããªã±ãŒã·ã§ã³ã§å®éã«è¡ãããŠããããšã«ã¯ããã«å¹æµããæ¹æ³ã§æ å ±ã衚瀺ããããŒã«ããããšèšã£ããã©ãã§ããããã ïŒ
æ¥é±ã®WWDCã®æºåã®ããã«1ãIïŒåïŒã¯ãåã®WWDCsããäŒè«ã®ã«ããã«ãèŠãŸããããšã«ãããã³ã¢ããŒã«ãããããçµ±åãã Xcode 10ã®ã«ã¹ã¿ã ããŒã«ãäœæããã®ãã¯ããã«ç°¡åã«ãªãããã«æžãçŽãããããšãå®å šã«èŠéããŸããããŸããWWDC 2019ã¯ãç§ãé·å¹Žæ¬ ããŠããããŒã«ã®çŽ æŽãããå ¥éæžã§ããããšãããããŸããã
ãã£ããããããŒã«ãé垞枬å®ããªããã®ã枬å®ããããã«ç¬èªã®ããŒã«ãæžãããšãã§ããããã«ãªããŸãããããããäœã枬å®ã§ããããã¯ã©ãã»ã©ç°¡åã§ããïŒ ãã»ãšãã©ãã¹ãŠããšãããã»ã©é£ããã¯ãªããååã«éãããšç§ã¯èšããŸããéåžžãå¿ èŠãªã®ã¯ãæšèãã€ã³ã¿ãã³ãŒãããããŒã«ã«è¡šç€ºããããã®ããŒã¿ã«å€æããæ¹æ³ã瀺ãXMLãã¡ã€ã«ãäœæããããšã ãã§ãããããè¡ãããã«å¿ èŠãªXMLã¯ãç¹ã«åã£ããã®ã§ã¯ãããŸãããäž»ãªé害ã¯ãããªããæžããã³ãŒãããããªããæ £ããŠãããã®ãšéåžžã«ç°ãªãå¯èœæ§ãé«ãããšã§ããäŸã¯ã»ãšãã©ãªããããã¥ã¡ã³ãã¯ãããè¡ãæ¹æ³ã®äžè¬çãªæŠèŠã®ã¿ãæäŸããŸããXcodeã¯å®éã«ã¯ããªãã§ããXMLãã¡ã€ã«ãå³å¯ã«æ€èšŒããèªåè£å®ã¯ãªãããšã©ãŒãèŠã€ãããããããã®ã¯ã»ãšãã©ãããŸãããããããå°ãæéãéãããåŸå¿ èŠãªèŠçŽ ãèŠã€ããããšãã§ããã³ãŒããé©å¿ãããäŸãããã°ãç©äºãéåžžã«è¿ éã«è¡ãããšãã§ããŸããããã§ã¯ãäŸãæããŠããã¹ãŠã®æçšãªãªã³ã¯ããªã¹ãããŠã¿ãŸãã
ãã ããæåããå§ããŸãããã以åã«CharlesãŸãã¯Wiresharkã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ããããã°ããããšãããããå€ãã®HTTPèŠæ±ãè¡ãã¢ããªã±ãŒã·ã§ã³ãéçºããããšãããæ¹ã¯ãã¢ããªã±ãŒã·ã§ã³çšã«ã«ã¹ã¿ãã€ãºãããHTTPãã¬ãŒã¹ããŒã«ãäœæã§ããããã«ããŠãã ãããå°ãªããšããã¬ãŒã ã¯ãŒã¯ã次ã®ããã«ãªããŸãã
ãã®ãããã¿ã€ãããã«ãããŠãããã°ããã®ã«çŽ1æ¥ããããŸããïŒé¢é£ããWWDCãããªãèŠãåŸïŒãã³ãŒã以å€ã«èå³ããªãå Žåã¯ãããã§ç¢ºèªã§ããŸãã
æŠèŠæŠèŠ
ã«ã¹ã¿ã ããŒã«ãäœæããæãç°¡åãªæ¹æ³ã¯ãos_signpostã䜿çšããããšã§ããããã¯ããŸãã«ããã§è¡ãããšã§ããããã䜿çšããŠãæšèãã€ã³ã¿.eventãŸãã¯.beginããã³.endããã°ã«èšé²ããŸããæ¬¡ã«ããããã®os_signpostééãåæãããã°ã€ã³ãã远å ã®å€ãæœåºããã«ã¹ã¿ã ããŒã«ãèšå®ããã°ã©ãã«è¡šç€ºããæ¹æ³ãã°ã«ãŒãåããæ¹æ³ããã£ã«ã¿ãªã³ã°ããæ¹æ³ãããŒã«ã®è©³çްãã€ã³ã«ãªã¹ããŸãã¯ããªãŒ/ãããŒãã£ãŒãã®æ§é ã衚瀺ããæ¹æ³ãèšå®ããŸãã ..ã
Webã©ã€ãã©ãªãééãããã¹ãŠã®HTTPãªã¯ãšã¹ããééïŒéå§+çµäºïŒãšããŠè¡šç€ºããããŒã«ãäœæããŠããããã®æèŠæéã確èªããã¢ããªã±ãŒã·ã§ã³ã§çºçããä»ã®ã€ãã³ããšçžé¢ãããããšèããŠããŸãããã®èšäºã§ã¯ãããŒã«ã®ãããã¯ãŒãã³ã°ã©ã€ãã©ãªãšããŠAlamofireã䜿çšãããããã¡ã€ãªã³ã°ã¢ããªã±ãŒã·ã§ã³ãšããŠWordpressã䜿çšããŸããããã¯ããããããªãŒãã³ãœãŒã¹ã§ããããã§ãããã ãããã¹ãŠã®ã³ãŒãããããã¯ãŒã¯ã©ã€ãã©ãªã«ç°¡åã«é©åãããããšãã§ããŸãã
ã¹ããã0ïŒInstrumentsã¢ããªããã§ãã¯ããŠãã ãã
- ( 411 WWDC 2019) â . «Orientation», , (instruments), (tracks), (lanes), (traces), (templates), (detail view) . .
- ( 410 WWDC 2018), , . , «Architecture» ( , , ) «Intermediate». , , , - . , , . , .
1: signpost-
éæšäžã«ããŒã«ãæ§ç¯ããããšèããŠããŸããã€ãŸããéæšãä»ããŠããŒã¿ããã°ã«èšé²ããŸãã Alamofireã¯ããªã¯ãšã¹ããéå§ãŸãã¯çµäºãããã³ã«éç¥ãéä¿¡ãããããå¿ èŠãªã®ã¯æ¬¡ã®2ã€ã ãã§ãã
NotificationCenter.default.addObserver(forName: Notification.Name.Task.DidResume, object: nil, queue: nil) { (notification) in
guard let task = notification.userInfo?[Notification.Key.Task] as? URLSessionTask,
let request = task.originalRequest,
let url = request.url else {
return
}
let signpostId = OSSignpostID(log: networking, object: task)
os_signpost(.begin, log: SignpostLog.networking, name: "Request", signpostID: signpostId, "Request Method %{public}@ to host: %{public}@, path: %@, parameters: %@", request.httpMethod ?? "", url.host ?? "Unknown", url.path, url.query ?? "")
}
NotificationCenter.default.addObserver(forName: Notification.Name.Task.DidComplete, object: nil, queue: nil) { (notification) in
guard let task = notification.userInfo?[Notification.Key.Task] as? URLSessionTask else { return }
let signpostId = OSSignpostID(log: networking, object: task)
let statusCode = (task.response as? HTTPURLResponse)?.statusCode ?? 0
os_signpost(.end, log: SignpostLog.networking, name: "Request", signpostID: signpostId, "Status: %@, Bytes Received: %llu, error: %d, statusCode: %d", "Completed", task.countOfBytesReceived, task.error == nil ? 0 : 1, statusCode)
}
ãªã¯ãšã¹ããéå§ããããšãæšèããã°ã«èšé²ãã
.beginå®äºãããšãæšèã远å ã.endãŸããé話ã®çµäºãšå¯Ÿå¿ããé話ã®éå§ãäžèŽãsignpostIdããããã«ãè€æ°ã®ãªã¯ãšã¹ãã䞊è¡ããŠçºçããŠããå Žåã«æ£ããééãéããããã«ããŸããçæ³çã«ã¯signpostIdããªã¯ãšã¹ããªããžã§ã¯ãã«æ ŒçŽããŠããšã«åããã®ã䜿çšããŠããããšã確èªããå¿
èŠã.beginãã.endãŸãããã ããRequestAlamofireã§ã¿ã€ããç·šéããããªãã£ãã®ã§OSSignpostID(log:, object:)ãIDãªããžã§ã¯ãã䜿çšããŠæž¡ãããšã«ããŸãããURLSessionTaskã©ã¡ãã®å Žåãåãã§ãããããããŒã¹ãªããžã§ã¯ãã䜿çšããŸããããã«ãããOSSignpostID(log:, object:)è€æ°ååŒã³åºããããšãã«åãèå¥åãè¿ãããšãã§ããŸãã
ãã©ãŒãããæååã䜿çšããŠããŒã¿ããã°ã«èšé²ããŸããããŒã«åŽã§ã®è§£æã容æã«ãããŸãè§£æã容æã«ããããã«ãããããåžžã«2ã€ã®åŒæ°ãæç¢ºã«å®çŸ©ãããæååã§åºåãå¿ èŠããããŸããã«
.endãã§ã«ãã°ã€ã³ããŠããå Žåã¯ãé話ã«ããŒã¿ãèšé²ããå¿
èŠããªãããšã«æ³šæããŠãã ãã.beginããããã¯1ã€ã®ééã«çµåãããã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã
ã¹ããã2ïŒXcodeã§æ°ããã«ã¹ã¿ã ããŒã«ãããžã§ã¯ããäœæããŸãã
ã«ã¹ã¿ã ã€ã³ã¹ãã«ã¡ã³ãã®äœæïŒWWDC 2018ã®ã»ãã·ã§ã³410ïŒãŸãã¯ã€ã³ã¹ãã«ã¡ã³ãã¢ããªã®ãã«ã-ããŒã«ããã¯ã¹ãããžã§ã¯ãã®äœæ ã®æé ã«åŸã£ãŠãXcodeã§æ°ããããŒã«ããã¯ã¹ãããžã§ã¯ããäœæããŸããããã«ãããã䜿çšããåºæ¬çãªXcodeãããžã§ã¯ããåŸãããŸã
.instrpkgãããã«ãã¹ãŠã®è©³çްã瀺ããŸãã
ã¹ããã3ïŒæ®ããè¡ã
åºæ¬çã«ãInstrumentsAppãã«ã-æšèããŒã¿ããããŒã«ãäœæããã§æŠèª¬ãããŠããæé ã«åŸããŸããããã§ã®ãã¹ãŠã®æé ã®èª¬æã¯æ£ããã§ãããããã§ã詳现ãäžè¶³ããŠãããããå®éã®ã«ã¹ã¿ã ããŒã«ã®äŸãç®ã®åã«çœ®ãããšããå§ãããŸããããªãã¯ããã§ç§ã®ãã®ãèŠãããšãã§ããŸããåºæ¬çã«ã次ã®éšåãå¿ èŠã«ãªããŸãã
ã¹ããŒã
ããã¯ãæšèãã€ã³ã¿ããã®ããŒã¿ã䜿çšå¯èœãªå€æ°ã«è§£æããæ¹æ³ãããŒã«ã«æç€ºããŸãããã°ã¡ãã»ãŒãžãã倿°ãæœåºããããããåã«åæ£ãããã³ãã¬ãŒããå®çŸ©ããŸãã
<os-signpost-interval-schema>
<id>org-alamofire-networking-schema</id>
<title>Alamofire Networking Schema</title>
<subsystem>"org.alamofire"</subsystem>
<category>"networking"</category>
<name>"Request"</name>
<start-pattern>
<message>"Request Method " ?http-method " to host: " ?host ", path: " ?url-path ", parameters: " ?query-parameters</message>
</start-pattern>
<end-pattern>
<message>"Status: " ?completion-status ", Bytes Received: " ?bytes-received ", error: " ?errored ", statusCode: " ?http-status-code</message>
</end-pattern>
<column>
<mnemonic>column-http-method</mnemonic>
<title>HTTP Method</title>
<type>string</type>
<expression>?http-method</expression>
</column>
<!-- -->
</os-signpost-interval-schema>
mnemonicåŸã§ãã®åãåç
§ããèå¥åã§ããã©ãããããããåã«å€æ°ãšåãååãä»ããã®ã¯å°ãå¥åŠã ãšæã£ãã®ã§ããããã®åã«æ¥é èŸãä»ããŸããcolumnãããããç§ãç¥ãéãããããè¡ãå¿
èŠã¯ãããŸããã
ããŒã«
ããŒã«ã¯ãåºæ¬çãªå®çŸ©ã§æ§æãããŠããŸãã
<instrument>
<id>org.alamofire.networking.instrument</id>
<title>Alamofire</title>
<category>Behavior</category>
<purpose>Trace HTTP calls made via Alamofire, grouped by method, host, path, etc.</purpose>
<icon>Network</icon>
<create-table>
<id>alamofire-requests</id>
<schema-ref>org-alamofire-networking-schema</schema-ref>
</create-table>
<!-- -->
</instrument>
ãšãŠãç°¡åã§ãããããã®ãã£ãŒã«ãã®ã»ãšãã©ã¯èªç±åœ¢åŒã®ããã¹ãã§ããããåã«å®çŸ©ããè³æã«é¢é£ããŠããŸãïŒ
schema-refïŒããããããããšããã§å®çŸ©ãããå€ã®å°ããªã»ããã®ã¿ãæã€ããšcategoryãiconã§ããŸããããŒã«å
ã®ã°ã©ãã°ã©ãã¯ãããŒã«ã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®ã°ã©ãã£ãã¯éšåãã€ãŸããã©ãã¯é åã«è¡šç€ºãããèŠèŠç衚çŸãå®çŸ©ããŸããããã¯æ¬¡ã®ããã«ãªããŸãã
<instrument>
<!-- -->
<graph>
<title>HTTP Requests</title>
<lane>
<title>the Requests</title>
<table-ref>alamofire-requests</table-ref>
<plot-template>
<instance-by>column-host</instance-by>
<label-format>%s</label-format>
<value-from>column-url-path</value-from>
<color-from>column-response</color-from>
<label-from>column-url-path</label-from>
</plot-template>
</lane>
</graph>
<!-- -->
</instrument>
ç°ãªãã¬ãŒã³ãæã€ããšãã§ããplot-templateã䜿çšããŠãã¬ãŒã³ããšã«åçãªæ°ã®ãããããå®è£ ã§ããŸããç§ã®äŸã«ã¯ãåçŽãªã°ã©ãã®äŸãå«ãŸããŠããŸããçç±ã¯ããããŸããã
graphãlaneã¿ã€ãã«ããããŸããããã«å ããŠãã®åãã£ãŒãã¯plot-templateããã©ãã«ãåãåãlabel-formatãŸãã
ãªã¹ããéèšããŸãã¯è©³çްãã¥ãŒã®ãããã
ãã£ãŒãã ãã§ã¯ãããŒã«ã¯ããäžå®å šã«èŠããŸãããŸãã詳现ãã¥ãŒã«äœãã衚瀺ããããšããŸããããªãããããè¡ãããšãã§ã
listãaggregationãŸãã¯narrativeãç§ããŸã äŒã£ãŠããªãããã«å€ãã®ãªãã·ã§ã³ããããããããŸãããéèšã¯æ¬¡ã®ããã«ãªããŸãã
<instrument>
<!-- -->
<aggregation>
<title>Summary: Completed Requests</title>
<table-ref>alamofire-requests</table-ref>
<slice>
<column>column-completion-status</column>
<equals><string>Completed</string></equals>
</slice>
<hierarchy>
<level>
<column>column-host</column>
</level>
<level>
<column>column-url-path</column>
</level>
</hierarchy>
<column><count/></column>
<column><average>duration</average></column>
<column><max>duration</max></column>
<column><sum>column-size</sum></column>
<column><average>column-size</average></column>
</aggregation>
<!-- -->
</instrument>
ãªã¹ãã¯æ¬¡ã®ããã«ãªããŸãã
<instrument>
<!-- -->
<list>
<title>List: Requests</title>
<table-ref>alamofire-requests</table-ref>
<column>start</column>
<column>duration</column>
<column>column-host</column>
<!-- ->
</list>
<!-- -->
</instrument>
ããŒãã¹çŽ æ
å®éãããããã¹ãŠã§ããããããããªãã¯WWDCãããªã§èª¬æãããŠãã以äžã®ããšãããŠããªãã®ã§ãããã€ãã®ã®ã£ãããåããããšãçŽæããŸããã
ç§ã®ãµã³ãã«ããŒã«ã«ã¯ãããã«ããã€ãã®åªããæ©èœãå«ãŸããŠããŸãããªã¯ãšã¹ããæåãããã©ããã«å¿ããŠééã«è²ãä»ãã
å°ããªCLIPSåŒãè²ã®å€ã¯ãInstruments Engineering TypeReferenceã«ãããŸãã ãã£ãŒããã³ãã¬ãŒãã䜿çšãããšã1ã€ã®ã¹ããªããã«è€æ°ã®ãã£ãŒãã衚瀺ããããããšãã°ãç§ã®äŸã®ããã«ãã¹ãããšã«ãã£ãŒããäœæãããã§ããŸãããã ããè€æ°ã®ã¬ãã«ã®éå±€ãèšå®ããŠããŠãŒã¶ãŒãããŒããå±éãŸãã¯æããããããšãã§ããããã«ããããšãã§ããŸãããã®ããã«ã¯ãèŠçŽ ã䜿çšããå¿ èŠããããŸãã
<engineering-type-track>éå±€ãå®çŸ©ããŠãããéå±€ã®ããŸããŸãªã¬ãã«ã«è¿œå ïŒæ¡åŒµïŒããŠãã°ã©ããšè©³çްãã¥ãŒã远å ããŸãããŸããããããã®ããŒã«å
ã§ã¢ããªã³ãã¢ã¯ãã£ãåããããšãå¿ããªãã§ãã ããã
ãããªãè¡å
以åã®ãªã³ã¯ãããŸã ãããèŠã€ããŠããªãå Žåã¯ãå®éã«ã¯ããã¡ã€ã«ã«å ¥ããããšãã§ãããã¹ãŠã®å®å šãªãã«ãããã
.instrpkgãŸããããšãã°ãããŒã«ã«éžæã§ããèŠçŽ <instrument>ãã¢ã€ã³ã³ãããããŸããéèŠãªãã€ã³ãã®1ã€ã¯ãé åºãéèŠã§ãããããã£ãŠãããšãã°ãã§ã¯<instrument>ã<title>ããåã«è¡šç€ºããå¿
èŠ<category>ããããŸããããããªããšã説æãç¡å¹ã«ãªããŸããã«ã¹ã¿ã ããŒã«
ã®äœæïŒWWDC 2018ã®ã»ãã·ã§ã³410ïŒãå床確èªããŠãå¿ èŠã«ãªãå¯èœæ§ã®ãã詳现ãã¡ã¢ããŸãã䜿çšäŸãèŠã€ããWWDC2019ã»ãã·ã§ã³ã®ãµã³ãã«ã³ãŒãããããŸã
<engineering-type-track>ã
CLIPSã¯ãã«ã¹ã¿ã ã¢ãã©ãŒïŒã¢ãã©ãŒ-ããã§ã¯èª¬æããŸããïŒã®äœæã«äœ¿çšãããèšèªã§ãããå宣èšäžã®çãåŒã«ã䜿çšã§ããŸããèšèªããã¥ã¡ã³ãã¯ãå¿ èŠãªãã®ãããã¯ããã«åºç¯å²ã§ããåçŽãªåŒãäœæããããã«ããããç¥ã£ãŠããå¿ èŠãããäž»ãªããšã¯ãCLIPSã¯ãã¬ãã£ãã¯ã¹è¡šèšã䜿çš
?a + ?bããããã代ããã«äœæããå¿
èŠããããšããããš(+ ?a ?b)ã§ãã
ã«ã¹ã¿ã ããŒã«ã«é¢ãããã®ä»ã®èšäº
Xcodeã§ã«ã¹ã¿ã ããŒã«ããã¯ã¹ãäœæããããšã«ã€ããŠã® Igor
ãããã°
XCodeos_signpostãã¬ãŒã¹ããã¥ã¡ã³ãã«
ããŒã«ã远å ããããšã¯åžžã«è¯ãèãã§ãããã®ããã«ããŠãäœããæåŸ
ã©ããã«æ©èœããªãå ŽåãããŒã¿ãæ£ãããã°ã«èšé²ãããŠãããã©ãããããã³ããŒã«ãããŒã¿ãæ£ããè§£éãããã©ããã確èªã§ããŸãã
ç§ããŸã çè§£ããŠããªãããš
- Instrumentsãããã©ã«ãã§æäŸããåå®çŸ©ã®åŒã§ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ïŒããšãã°ãæéïŒã«è¡šç€ºããå€ã䜿çšããæ¹æ³ïŒããšãã°ãåä¿¡ãããã€ããæéã§å²ã£ãŠããŒã¬ãŒãåãäœæããããïŒã
- äœåãªè©³çްé åã«äœãã衚瀺ããæ¹æ³ãã³ãŒã«ã¹ã¿ãã¯å°çšã®ããã§ããããšãã°ãéžæãããªã¯ãšã¹ãã®JSONæ¬æã衚瀺ãããã®ã§ããããããæç¢ºã«ããäŸãèŠã€ãããŸããã
ãã®ããŒã«ã®æ©èœ
ãŸã é²è¡äžã®äœæ¥
ããŠã³ããŒãããŠãèªåã®ç®ã§ç¢ºãããŠãã ããã
èæ³š
- ããŠãå®éã«ã¯ä»ã®çç±ããããŸããã
- ç§ã®äŸã«ãã°ã€ã³ããããã®å®å šãªã³ãŒãã¯ãLogger.swiftãã¡ã€ã«ã«ãããŸããAlamofire 5ã¯å·çæç¹ã§ãã§ã«ãªãªãŒã¹ãããŠããŸãããWordpress iOSã¢ããªã®çŸåšã®ããŒãžã§ã³ã§äœ¿çšãããŠãããããAlamofire4.8ã§æ³å®ãããŠããŸããéç¥ãããããããã®ãã®ã³ã°ã³ãŒãã¯ãAlamofireèªäœã倿Žããã«ç°¡åã«è¿œå ã§ããŸãããã«ã¹ã¿ã ãããã¯ãŒãã³ã°ã©ã€ãã©ãªãããå Žåã¯ãã©ã€ãã©ãªèªäœã«ãšã³ããªã远å ããŠè©³çްã«ã¢ã¯ã»ã¹ããæ¹ãç°¡åãªå ŽåããããŸãã
iOSéçºã®ã¯ã€ãã¯ã¹ã¿ãŒãïŒç¡æã®ãŠã§ãããŒïŒ