๊ณต๋ถ€ ์—ฐ์Šต์žฅ :-)

Using Responders and the Responder Chain to Handle Events ๋ฒˆ์—ญ

|

Responder Chain์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ ์• ํ”Œ ๊ฐœ๋ฐœ์ž ๋ฌธ์„œ์— ์žˆ๋Š” article์„ ๋ฒˆ์—ญํ•˜์—ฌ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค. ๊ฐœ์ธ ๊ณต๋ถ€์šฉ์œผ๋กœ ๋งค์šฐ roughํ•˜๊ฒŒ ๋ฒˆ์—ญํ•˜๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ด๋ผ ์˜ค์—ญ ๋งŽ์„ ์ˆ˜ ์žˆ์Œ!

Using Responders and the Responder Chain to Handle Events

์ฐธ๊ณ ๋งํฌ

  • ์•ฑ์€ responder ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•œ๋‹ค.
  • responder๊ฐ์ฒด๋Š” UIResponderํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ด๊ณ , ๊ณตํ†ต์ ์œผ๋กœ UIView, UIViewController, UIApplication๊ฐ์ฒด๋ฅผ ์„œ๋ธŒํด๋ž˜์Šคํ•œ๋‹ค.
  • Responder๋Š” ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•˜๊ณ , ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ responder๊ฐ์ฒด๋กœ(ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”)์ „๋‹ฌํ•ด์•ผํ•œ๋‹ค.
  • ์•ฑ์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์œผ๋ฉด UIKit์€ ๊ฐ€์žฅ ์ ์ ˆํ•œ first responder์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ธ๋‹ค.

  • ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€(Unhandled)์ด๋ฒคํŠธ๋Š” responder chain์— ์˜ํ•ด์„œ responder๊ฐ์ฒด๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • ๋งŒ์•ฝ ํ…์ŠคํŠธํ•„๋“œ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜์ง€ ์•Š์œผ๋ฉด, UIKit์€ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์œ„ UIView๋กœ ๋ณด๋‚ธ๋‹ค.
  • ์œˆ๋„์šฐ๊นŒ์ง€ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋์Œ์—๋„ ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋ฆฌํ•  ์ˆ˜ ์—†์œผ๋ฉด, ์ด๋ฒคํŠธ๋Š” UIApplication๊นŒ์ง€ ์ „๋‹ฌ๋˜๋ฉฐ, and possibly to the app delegate if that object is an instance of UIResponder and not already part of the responder chainโ€ฆ.??

์ด๋ฒคํŠธ์˜ first responder๊ฒฐ์ •ํ•˜๊ธฐ

UIKit์€ ์ด๋ฒคํŠธ์˜ ํƒ€์ž…์— ๋”ฐ๋ผ์„œ FirstResponder ๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•œ๋‹ค.

  • Touch event: ํ„ฐ์น˜๊ฐ€ ์ผ์–ด๋‚œ ๋ทฐ
  • Press event: ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง„ ๋ทฐ(The object that has focus.)
  • Shake-motion event: ๋‚ด๊ฐ€ ์ง€์ •ํ•œ ๊ฐ์ฒด (The object that you (or UIKit) designate.)
  • Remote-Control event: ๋‚ด๊ฐ€ ์ง€์ •ํ•œ ๊ฐ์ฒด (The object that you (or UIKit) designate.)
  • Editing menu messages: ๋‚ด๊ฐ€ ์ง€์ •ํ•œ ๊ฐ์ฒด (The object that you (or UIKit) designate.) ๋ฆฌ๋ชจํŠธ์ปจํŠธ๋กค์ด๋ž‘ editing menu๊ฐ€ ๋ญ์ง€..

cf) Core Motion Framework

Motion events related to the accelerometers, gyroscopes, and magnetometer do not follow the responder chain. Instead, Core Motion delivers those events directly to the designated object. For more information, see Core Motion Framework

  • ์ปจํŠธ๋กค์€ ์ž์‹ ๋“ค๊ณผ ๊ด€๋ จ๋œ ํƒ€๊ฒŸ ๊ฐ์ฒด์™€ ์•ก์…˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๋‹ค.
  • ์ปจํŠธ๋กค์˜ ํƒ€๊ฒŸ ๊ฐ์ฒด๊ฐ€ nil์ผ๋•Œ, UIKit์€ ์˜ฌ๋ฐ”๋ฅธ ์•ก์…˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ตฌํ˜„๋œ ๊ฐ์ฒด๋ฅผ ์ฐพ์•„์„œ ํƒ€๊ฒŸ ๊ฐ์ฒด๋ถ€ํ„ฐ responder chain๊นŒ์ง€ ์ง€๋‚˜๋‹ค๋‹Œ๋‹คโ€ฆํƒ์ƒ‰ํ•œ๋‹คโ€ฆ์ฐพ์•„๋‹ค๋‹Œ๋‹คโ€ฆ?
  • For example, the UIKit editing menu uses this behavior to search for responder objects that implement methods with names like cut(:), copy(:), or paste(_:).
  • Action messages are not events, but they may still take advantage of the responder chain.
  • GestureRecognizer๋Š” touch๋‚˜ press ์ด๋ฒคํŠธ๋ฅผ ์ž์‹ ์˜ ๋ทฐ๋ณด๋‹ค ๋จผ์ž ๋ฐ›๋Š”๋‹ค
  • ๋งŒ์•ฝ ๋ทฐ์˜ GestureRecognizer๊ฐ€ ํ„ฐ์น˜ ์‹œํ€€์Šค๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜๋ฉด, UIKit์€ ๋ทฐ์— ํ•ด๋‹น ํ„ฐ์น˜์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ธ๋‹ค.
  • ๋งŒ์•ฝ ๋ทฐ๊ฐ€ ํ„ฐ์น˜๋ฅผ ํ•ธ๋“ค๋ง ํ•˜์ง€ ๋ชปํ•˜๋ฉด, UIKit์€ Responder chain์— ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ธ๋‹ค.

์–ด๋–ค Responder๊ฐ€ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ

  • UIKit์€ ์–ด๋””์„œ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚ฌ๋Š”์ง€ ์•Œ๊ธฐ์œ„ํ•ด ๋ทฐ ๊ธฐ๋ฐ˜์˜ hit-testing์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • UIKit์€ ๋ทฐ ๊ณ„์ธต๊ตฌ์กฐ์— ์žˆ๋Š” ๋ทฐ๋“ค์˜ bound์˜ ์œ„์น˜๋ฅผ ๋น„๊ตํ•˜๋ฉฐ ํ„ฐ์น˜์˜ ์œ„์น˜๋ฅผ ๋น„๊ตํ•œ๋‹ค.
  • hitTest()๋ฉ”์†Œ๋“œ๋Š” ๋ทฐ ๊ณ„์ธต๊ตฌ์กฐ๋ฅผ ๊ฐ€๋กœ์ง€๋ฅด๋ฉด์„œ, ๊ฐ€์žฅ ๊นŠ์€ ๋‹จ์— ์žˆ๋Š” ์„œ๋ธŒ๋ทฐ๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉด์„œ ํŠน์ • ํ„ฐ์น˜๋ฅผ ํฌํ•จํ•œ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ฐพ์•„๋‚ธ๋‹ค.
  • ํ„ฐ์น˜ ๋กœ์ผ€์ด์…˜์ด๋‚˜ ๋‹ค๋ฅธ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, UIKit์€ ๋˜‘๊ฐ™์€ UITouch ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ์šด ์ •๋ณด์™€ ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  • (๋งŒ์•ฝ ํ„ฐ์น˜ ์œ„์น˜๊ฐ€ ์›๋ž˜ ๋ทฐ๋ฅผ ๋ฒ—์–ด๋‚˜๋„, ํ„ฐ์น˜๊ฐ์ฒด ๋‚ด์˜ view ํ”„๋กœํผํ‹ฐ๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค.)
  • ํ„ฐ์น˜๊ฐ€ ๋๋‚˜๋ฉด UIKit์€ UITouch๊ฐ์ฒด๋ฅผ ๋ฆด๋ฆฌ์ฆˆํ•œ๋‹ค.

Responder Chain์„ ๋ฐ”๊พธ๊ธฐ

  • next ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•จ์œผ๋กœ์จ ๋ฆฌ์Šคํฐ๋”์ฒด์ธ์„ ๋ณ€๊ฒฝ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • (When you do this, the next responder is the object that you return.)
  • UIKit ํด๋ž˜์Šค๋“ค์€ ์ด๋ฏธ ์ด ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ํŠน์ •ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜์—ฌ ์ด๋ฏธ ์ด ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ตฌํ˜„ํ•ด๋†จ๋‹ค.
    • UIView objects. If the view is the root view of a view controller, the next responder is the view controller; otherwise, the next responder is the viewโ€™s superview.

    • UIViewController objects.
      • If the view controllerโ€™s view is the root view of a window, the next responder is the window object.

      • If the view controller was presented by another view controller, the next responder is the presenting view controller.

    • UIWindow objects. The windowโ€™s next responder is the UIApplication object.

    • UIApplication object. The next responder is the app delegate, but only if the app delegate is an instance of UIResponder and is not a view, view controller, or the app object itself.

TIL_20180625 ~ 20180629

|

์›น๋ทฐ์•ฑ ๋ฏธ์…˜๊ณผ WKWebKit์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜๊ณ  ๊ณต๋ถ€ํ•œ ์ผ์ฃผ์ผ..์›น์„ ๋ชจ๋ฅด๋Š” ์ƒํƒœ์—์„œ WK๋ญ”๊ฐ€ ๋‚ ์งœ๋ณ„๋กœ ๋‚˜๋ˆ ์„œ ์ •๋ฆฌํ•ด์„œ ๋‚จ๊ฒจ๋†“์€๊ฒŒ ์—†์–ด์„œ ๊ทธ๋ƒฅ ์ผ์ฃผ์ผ๋™์•ˆ ๊ณต๋ถ€ํ•œ ํ”์ ์œผ๋กœ TIL๋Œ€์ฒด.. :(

๋ Œ๋”๋ง: ์š”์ฒญ๋ฐ›์€ ์ผ์„ ๋ธŒ๋ผ์šฐ์ € ํ™”๋ฉด์— ํ‘œ์‹œ

func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!)

  • The above is a WKNavigationDelegate protocol method that gets called several times during the page load.
  • One of its parameters is an WKNavigationAction object which contains information that can help you decide whether to continue page load or not.
    • WKNavigationAction๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น๋ทฐ๋ฅผ ๊ณ„์† ๋กœ๋“œํ• ์ง€ ๋ง์ง€ ๊ฒฐ์ •ํ•˜๋ฉฐ, ์ด๋ฅผ ์œ„ํ•ด์„œ WKNavigationAction์˜ ์•„๋ž˜ ์†์„ฑ๋“ค์„ ์ด์šฉํ•œ๋‹ค.
    • request
    • sourceFrame
    • targetFrame
  • WKNavigationActionPolicy
    • .cancel
    • .allow: the page loads as usual and renders in the web view

    func safariViewController(SFSafariViewController, didCompleteInitialLoad: Bool) > ์ด๊ฒŒ ํ˜ธ์ถœ๋˜๋ฉด ์ปดํ”Œ๋ฆฌ์…˜ํ•ธ๋“ค๋Ÿฌ ํ˜ธ์ถœ๋˜๋„๋ก..?

    func safariViewControllerDidFinish(SFSafariViewController) Tells the delegate that the user dismissed the view. > ์‚ฌํŒŒ๋ฆฌ ๋ทฐ์ปจ ๋„๊ธฐ

ํ™”๋ฉด์ด ๋‹ค ๋œฐ๋•Œ๊นŒ์ง€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” postMessage๋ฅผ ํ•œ๋‹ค. load๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ๋กœ๋”ฉ์ด ์ง„ํ–‰๋˜๋Š” ์ค‘์— navigation์ด๋‚˜ scriptmessageHandler๋Š” ํ™œ์„ฑํ™” ๋˜์„œ ๊ณ„์† ๊ทธ ๋™์ž‘์ด ์žˆ๋Š”์ง€ ์ฐพ์Œ ๋กœ๋”ฉ์ด ์ง„ํ–‰๋˜๋Š” ์ค‘์— js๊ฐ€ ๊ณ„์† ๋ฉ”์‹œ์ง€๋ฅผ postํ•˜๋Š”๊ฑฐ๊ฐ™์Œ ์™„์ „ํžˆ ๋กœ๋“œ๋˜๋ฉด postMessage๋ฅผ ํ•˜์ง€ ์•Š์Œ

์ปดํ”Œ๋ฆฌ์…˜ ํ•ธ๋“ค๋Ÿฌ ๋‘๋ฒˆํ˜ธ์ถœ๋˜๋ฉด ์—๋Ÿฌ๋‚จ navigationType์˜ allow์™€ cancel

URL: https://m.baeminchan.com/
search failed!
URL: about:blank
search failed!
URL: https://m.baeminchan.com/search.php
search success!
2018-06-25 14:39:09.808320+0900 WebViewApp[94065:10947861] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[WebViewApp.ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was called more than once'
*** First throw call stack:
(
	0   CoreFoundation                      0x0000000111bd11e6 __exceptionPreprocess + 294
	1   libobjc.A.dylib                     0x000000010d6d5031 objc_exception_throw + 48
	2   CoreFoundation                      0x0000000111c46975 +[NSException raise:format:] + 197
	3   WebKit                              0x000000011014d897 _ZNK6WebKit28CompletionHandlerCallChecker30completionHandlerHasBeenCalledEv + 203
	4   WebKit                              0x000000011018b462 _ZZN6WebKit15NavigationState16NavigationClient31decidePolicyForNavigationActionERNS_12WebPageProxyEON3WTF3RefIN3API16NavigationActionENS4_13DumbPtrTraitsIS7_EEEEONS5_INS_27WebFramePolicyListenerProxyENS8_ISC_EEEEPNS6_6ObjectEEN3$_1clE24WKNavigationActionPolicyP18_WKWebsitePolicies + 36
	5   WebViewApp                          0x000000010cdc8429 _T0SC24WKNavigationActionPolicyOIeyBy_ABIegy_TR + 25
	6   WebViewApp                          0x000000010cdc849d _T0SC24WKNavigationActionPolicyOIeyBy_ABIegy_TRTA + 13
	7   WebViewApp                          0x000000010cdc8303 _T010WebViewApp0B10ControllerC03webB0ySo05WKWebB0C_So18WKNavigationActionC15decidePolicyForySC0ghJ0Oc15decisionHandlertF + 1795
	8   WebViewApp                          0x000000010cdc83fc _T010WebViewApp0B10ControllerC03webB0ySo05WKWebB0C_So18WKNavigationActionC15decidePolicyForySC0ghJ0Oc15decisionHandlertFTo + 156
	9   WebKit                              0x000000011018886a _ZN6WebKit15NavigationState16NavigationClient31decidePolicyForNavigationActionERNS_12WebPageProxyEON3WTF3RefIN3API16NavigationActionENS4_13DumbPtrTraitsIS7_EEEEONS5_INS_27WebFramePolicyListenerProxyENS8_ISC_EEEEPNS6_6ObjectE + 752
	10  WebKit                              0x000000011033fec0 _ZN6WebKit12WebPageProxy31decidePolicyForNavigationActionEyRKN7WebCore18SecurityOriginDataEyONS_20NavigationActionDataERKNS_13FrameInfoDataEyRKNS1_15ResourceRequestEOSA_yRKNS_8UserDataERbRyRNS1_12PolicyActionERNS_10DownloadIDERSt8optionalINS_19WebsitePoliciesDataEE + 1286
	11  WebKit                              0x000000011037076a _ZN3IPC22callMemberFunctionImplIN6WebKit12WebPageProxyEMS2_FvyRKN7WebCore18SecurityOriginDataEyONS1_20NavigationActionDataERKNS1_13FrameInfoDataEyRKNS3_15ResourceRequestEOSC_yRKNS1_8UserDataERbRyRNS3_12PolicyActionERNS1_10DownloadIDERSt8optionalINS1_19WebsitePoliciesDataEEENSt3__15tupleIJyS4_yS7_S9_ySC_SC_ySG_EEEJLm0ELm1ELm2ELm3ELm4ELm5ELm6ELm7ELm8ELm9EENSW_IJbySL_SN_SR_EEEJLm0ELm1ELm2ELm3ELm4EEEEvPT_T0_OT1_RT3_NSV_16integer_sequenceImJXspT2_EEEENS16_ImJXspT4_EEEE + 139
	12  WebKit                              0x0000000110365da2 _ZN3IPC13handleMessageIN8Messages12WebPageProxy31DecidePolicyForNavigationActionEN6WebKit12WebPageProxyEMS5_FvyRKN7WebCore18SecurityOriginDataEyONS4_20NavigationActionDataERKNS4_13FrameInfoDataEyRKNS6_15ResourceRequestEOSF_yRKNS4_8UserDataERbRyRNS6_12PolicyActionERNS4_10DownloadIDERSt8optionalINS4_19WebsitePoliciesDataEEEEEvRNS_7DecoderERNS_7EncoderEPT0_T1_ + 322
	13  WebKit                              0x0000000110185d7d _ZN3IPC18MessageReceiverMap19dispatchSyncMessageERNS_10ConnectionERNS_7DecoderERNSt3__110unique_ptrINS_7EncoderENS5_14default_deleteIS7_EEEE + 141
	14  WebKit                              0x00000001103bc4d2 _ZN6WebKit15WebProcessProxy21didReceiveSyncMessageERN3IPC10ConnectionERNS1_7DecoderERNSt3__110unique_ptrINS1_7EncoderENS6_14default_deleteIS8_EEEE + 28
	15  WebKit                              0x0000000110150343 _ZN3IPC10Connection19dispatchSyncMessageERNS_7DecoderE + 209
	16  WebKit                              0x000000011014dcba _ZN3IPC10Connection15dispatchMessageENSt3__110unique_ptrINS_7DecoderENS1_14default_deleteIS3_EEEE + 104
	17  WebKit                              0x000000011015056b _ZN3IPC10Connection18dispatchOneMessageEv + 177
	18  JavaScriptCore                      0x000000011a9b33ac _ZN3WTF7RunLoop11performWorkEv + 236
	19  JavaScriptCore                      0x000000011a9b3652 _ZN3WTF7RunLoop11performWorkEPv + 34
	20  CoreFoundation                      0x0000000111b73bb1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
	21  CoreFoundation                      0x0000000111b584af __CFRunLoopDoSources0 + 271
	22  CoreFoundation                      0x0000000111b57a6f __CFRunLoopRun + 1263
	23  CoreFoundation                      0x0000000111b5730b CFRunLoopRunSpecific + 635
	24  GraphicsServices                    0x00000001144c8a73 GSEventRunModal + 62
	25  UIKit                               0x000000010df71057 UIApplicationMain + 159
	26  WebViewApp                          0x000000010cdc9ec7 main + 55
	27  libdyld.dylib                       0x0000000112db2955 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

์›น๋ทฐ ๋งˆ์ง€๋ง‰ ๋งˆ๋ฌด๋ฆฌ ์•ฑ ๋‚ด์—์„œ ์›น๋ทฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ์›น์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ , ๋™์‹œ์— ์›น์˜ ๋™์ž‘์„ ํ†ต์ œํ•  ์ˆ˜๋„ ์žˆ์Œ WKScriptMessageHandler- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์›นํŽ˜์ด์ง€๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ ๋ณด๋‚ด๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์ž‘์„ ํ•˜๋Š” ํ”„๋กœํ† ์ฝœ WKUserContentController- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์›น๋ทฐ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ  user script๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ WKNavigationDelegate- ์›น์˜ ํƒ์ƒ‰ ๊ณผ์ •์ค‘ ํŠน์ •ํ•œ ํƒ€์ด๋ฐ์— ๋งž๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœ์‹œํ‚ด. ์ด์— ๋งž์ถฐ์„œ ์ ์ ˆํ•œ custom๋™์ž‘์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. SFSafariViewController- ์•ฑ ๋‚ด์—์„œ ์›น์„ ์‚ฌํŒŒ๋ฆฌ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋„์šฐ๊ณ  ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‚ฌํŒŒ๋ฆฌ์˜ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•˜๊ณ ์žˆ๋‹ค.

์ฐธ๊ณ ํ–ˆ๋˜ ๋งํฌ๋“ค : https://www.appcoda.com/webkit-framework-tutorial/

ํ•œ๊ธ€ ์ธ์ฝ”๋”ฉ์˜ ์ดํ•ด(์œ ๋‹ˆ์ฝ”๋“œ) ์™„์ „ ๊ธฐ์ดˆ!

|

์ฃผ์†Œ๋ก ์•ฑ ๋งŒ๋“ค๊ธฐ ์ค‘ ์—ฐ๋ฝ์ฒ˜ ๋ฐ์ดํ„ฐ์˜ ์ด๋ฆ„์— ์ดˆ์„ฑ ๋ถ„์„์ด ํ•„์š”ํ•ด์„œ swift์˜ UnicodeScalar๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์•ผ ํ–ˆ๋Š”๋ฐ, ์œ ๋‹ˆ์ฝ”๋“œ์™€ ํ•œ๊ธ€ ์ธ์ฝ”๋”ฉ์„ ์ฒ˜์Œ ์ ‘ํ•ด๋ด์„œ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ํ—ค๋งธ๋‹ค. ํ•œ๊ธ€ ์ธ์ฝ”๋”ฉ๊ณผ ์œ ๋‹ˆ์ฝ”๋“œ์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์ธ ๋‚ด์šฉ๋งŒ ์ดํ•ดํ•œ๋Œ€๋กœ ์ •๋ฆฌํ•œ ๊ธ€! ์•„๋ž˜์˜ ๊ธ€์„ ์ฐธ๊ณ ํ•ด์„œ ์ž‘์„ฑํ–ˆ๋‹ค.

ํ‘œ์ค€ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ

  • ex) ASCII. ์˜์–ด ๋ฌธ์ž ์ง‘ํ•ฉ์˜ ์‹œ์ดˆ
  • ์ปดํ“จํ„ฐ ๊ฐ„์— ๋ฌธ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•˜๊ธฐ์œ„ํ•ด ๋ฌธ์ž์ง‘ํ•ฉ์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„(์ธ์ฝ”๋”ฉ)

ํ•œ๊ธ€์˜ ๋ฌธ์ž ์ง‘ํ•ฉ

๋ฌธ์ž ์ง‘ํ•ฉ: ๋ฌธ์ž๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ€์žฅ ๋จผ์ € โ€˜๋ฌธ์ž ์ง‘ํ•ฉโ€™์„ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค. ๋ฌธ์ž ์ง‘ํ•ฉ์€ ํ‘œํ˜„ํ•ด์•ผ ํ•  ๋ฌธ์ž๋ฅผ ์ •ํ•˜๊ณ  ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•œ ๊ฒƒ.

  • ์˜์–ด: โ€˜Aโ€™ ~ โ€˜zโ€™ (๋Œ€๋ฌธ์ž์—์„œ ์†Œ๋ฌธ์ž๊นŒ์ง€)
  • ํ•œ๊ธ€: โ€˜๊ฐ€โ€™ ~ โ€˜ํžฃโ€™
  • CCS: coded character set. ์ด๋Ÿฌํ•œ ๋ฌธ์ž ์ง‘ํ•ฉ์„ ํ–‰๋ ฌ๋กœ ํ‘œ๊ธฐํ•œ ํ˜•ํƒœ
  • CES: character encoding scheme. ๋ฌธ์ž ์ง‘ํ•ฉ์„ ์ปดํ“จํ„ฐ์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ 8๋น„ํŠธ ๋‹จ์œ„ ํ˜•ํƒœ๋กœ ํ‘œํ˜„ํ•œ ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹
  • ํ•œ๊ธ€ ํ‘œํ˜„ ๋ฐฉ๋ฒ•
    • ์กฐํ•ฉํ˜•: ํ•œ๊ธ€์˜ ์›๋ฆฌ์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ดˆ์„ฑ, ์ค‘์„ฑ, ์ข…์„ฑ์— ๊ฐ๊ฐ ์ฝ”๋“œ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹
    • ์™„์„ฑํ˜•: โ€˜๊ฐ€โ€™,โ€™๊ฐโ€™,โ€™๊ฐ„โ€™๊ณผ๊ฐ™์ด ์™„์„ฑ๋œ ๋ฌธ์ž์— ์ฝ”๋“œ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹. ํ•œ๊ธ€ ํ‘œ์ค€์•ˆ์ด๋‹ค.

์œ ๋‹ˆ์ฝ”๋“œ

  • ๊ฐ ๋‚˜๋ผ ์–ธ์–ด์—๋Š” ์ปดํ“จํ„ฐ์—์„œ ํ•ด๋‹น ์–ธ์–ด๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋…์ž์ ์ธ ๋ฌธ์ž ์ง‘ํ•ฉ์ด ์žˆ์Œ
  • ํ•˜์ง€๋งŒ ๋ฌธ์ œ๋Š” โ€˜์–ด๋–ป๊ฒŒ ๋™์‹œ์— ํ•œ๊ตญ์–ด, ์ค‘๊ตญ์–ด, ์ผ๋ณธ์–ด๋ฅผ ํ‘œํ˜„ํ•˜๋Š๋ƒโ€™
  • ํ•˜๋‚˜์˜ ๋ฌธ์ž ์ง‘ํ•ฉ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์„œ์—์„œ๋Š” ๋‹ค๊ฐœ๊ตญ์–ด๋ฅผ ๋™์‹œ์— ํ‘œํ˜„ํ•  ์ˆ˜ ์—†์—ˆ์Œ
  • ์œ ๋Ÿฝ์–ด์˜ ๋ฌธ์ž๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ฐ™์€ ๋ฌธ์ž์ง€๋งŒ ๋ฌธ์ž์ง‘ํ•ฉ์— ๋”ฐ๋ผ ์ฝ”๋“œ๊ฐ€ ๋‹ฌ๋ž์Œ
  • ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ๋ฌธ์ž ์ง‘ํ•ฉ์„ ํ•˜๋‚˜๋กœ ๋ชจ์•„ ํƒ„์ƒ์‹œํ‚จ ๊ฒƒ์ด ์œ ๋‹ˆ์ฝ”๋“œ.
  • ํ˜„์žฌ ๋ฒ„์ „์€ 2010๋…„ 10์›” 11์ผ ์ œ์ •๋œ 6.0์ด๋‹ค.

์œ ๋‹ˆ์ฝ”๋“œ ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹

๋ฌธ์ž ์ธ์ฝ”๋”ฉ์€ ๋ฌธ์ž๋“ค์˜ ์ง‘ํ•ฉ์„ ๋ถ€ํ˜ธํ™”(์ •๋ณด์˜ ํ˜•ํƒœ๋‚˜ ํ˜•์‹์„ ๋ณ€ํ™˜ํ•˜๋Š” ์ฒ˜๋ฆฌ)ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

  • ์œ ๋‹ˆ์ฝ”๋“œ์˜ ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ๋Š” ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ์ฝ”๋“œํ™”ํ•œ UCS-2์™€ UCS-4, ๋ณ€ํ™˜ ์ธ์ฝ”๋”ฉ ํ˜•์‹(UTF, UCS Transformation Format)์ธ UTF-7, UTF-8, UTF-16, UTF-32 ์ธ์ฝ”๋”ฉ ๋“ฑ์ด ์žˆ์Œ
  • ์ด ์ค‘ ASCII์™€ ํ˜ธํ™˜์ด ๊ฐ€๋Šฅํ•˜๋ฉด์„œ ์œ ๋‹ˆ์ฝ”๋“œ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” UTF-8 ์ธ์ฝ”๋”ฉ์ด ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋จ

์ฝ”๋“œํฌ์ธํŠธ

์œ ๋‹ˆ์ฝ”๋“œ์˜ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๊ธฐ์œ„ํ•ด์„œ๋Š” ์ฝ”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋ณดํ†ต U+๋ฅผ ๋ถ™์—ฌ ํ‘œ์‹œํ•จ

  • ex) Aโ€™์˜ ์œ ๋‹ˆ์ฝ”๋“œ ๊ฐ’์€ U+0041๋กœ ํ‘œํ˜„ํ•œ๋‹ค(\u0041๋กœ ํ‘œ๊ธฐํ•˜๊ธฐ๋„ ํ•จ)
  • ์ด ์ค‘ ํ•œ๊ธ€์€ U+1100~U+11FF ์‚ฌ์ด์— ํ•œ๊ธ€ ์ž๋ชจ ์˜์—ญ, U+AC00~U+D7AF ์‚ฌ์ด์˜ ํ•œ๊ธ€ ์†Œ๋ฆฌ ๋งˆ๋”” ์˜์—ญ์— ํฌํ•จ๋œ๋‹ค.

์œ ๋‹ˆ์ฝ”๋“œ ๋ฒ”์œ„ ๋ชฉ๋ก์—์„œ ํ•œ๊ธ€ ๊ด€๋ จ ๋ฒ”์œ„

ํ•œ๊ธ€ํ‘œํ˜„์˜ ๋Œ€ํ‘œ์  ๋‘ ๊ฐœ์˜ ์ฝ”๋“œ์˜์—ญ

  • ํ•œ๊ธ€ ์†Œ๋ฆฌ ๋งˆ๋””์™€ ํ•œ๊ธ€์ž๋ชจ, ํ•œ๊ธ€ ์ž๋ชจ ํ™•์žฅ ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ์˜ ์ฝ”๋“œ ์˜์—ญ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๊ฐ™์€ ๊ธ€์ž๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐœ์˜ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.
  • ๊ฐ™์€ โ€˜๊ฐ€โ€™์˜ ๊ธ€์ž์—ฌ๋„, ํ‘œํ˜„๋ฒ•์— ๋”ฐ๋ผ ์ฝ”๋“œ ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค๋Š” ์˜๋ฏธ.

ํ•œ๊ธ€ ์†Œ๋ฆฌ๋งˆ๋””

  • ์ดˆ์„ฑ, ์ค‘์„ฑ, ์ข…์„ฑ์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ํ•œ๊ธ€์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์˜์—ญ
  • ํ˜„๋Œ€ ํ•œ๊ธ€์—์„œ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•œ 11,172์ž๋ฅผ ๋ชจ๋‘ ํฌํ•จ (โ€˜๊ฐ€โ€™ ~ โ€˜ํžฃโ€™)
  • โ€˜๊ฐ€โ€™(U+AC00) ~ โ€˜ํžฃโ€™(U+D7A3)
  • ์™„์„ฑ๋œ ๊ธ€์ž ํ•˜๋‚˜ํ•˜๋‚˜์— ์ฝ”๋“œ๋ฅผ ๋งค์นญ
  • ๊ฐ ์Œ์ ˆ์€ ์ดˆ์„ฑ, ์ค‘์„ฑ, ์ข…์„ฑ ์ˆœ์œผ๋กœ ์ •๋ ฌ
  • ํ™•์žฅ ์™„์„ฑํ˜•๊ณผ ๋‹ค๋ฅธ ์ ์€, ์ดˆ์„ฑ, ์ค‘์„ฑ, ์ข…์„ฑ์˜ ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ
  • ์ดˆ์„ฑ์€ 19๊ฐœ, ์ค‘์„ฑ์€ 21๊ฐœ, ์ข…์„ฑ์€ 28๊ฐœ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ
  • ์œ ๋‹ˆ์ฝ”๋“œ ํ•œ๊ธ€์˜ ๊ฐ ์Œ์†Œ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ธฐ ์ฐธ๊ณ 

ํ•œ๊ธ€ ์ž๋ชจ, ํ•œ๊ธ€ ์ž๋ชจ ํ™•์žฅ

  • ์ดˆ์„ฑ/์ข…์„ฑ์„ ๊ตฌ๋ณ„ํ•˜๋Š” ์ž์Œ๊ณผ ๋ชจ์Œ์œผ๋กœ ๊ตฌ์„ฑ
  • ์™„์„ฑ(์กฐํ•ฉ ์ „) ๋ฌธ์ž ํ•˜๋‚˜ํ•˜๋‚˜์— ์ฝ”๋“œ ๋งค์นญ
  • ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์กฐํ•ฉํ˜• ํ•œ๊ธ€์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
  • ํ•œ๊ธ€ ์ž๋ชจ ์˜์—ญ์—๋Š” ์˜›ํ•œ๊ธ€์—์„œ๋งŒ ์‚ฌ์šฉ๋œ ์ดˆ์„ฑ, ์ค‘์„ฑ, ์ข…์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ, ์˜›ํ•œ๊ธ€์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
  • U+1100๋ถ€ํ„ฐ U+115E๊นŒ์ง€๋Š” ์ดˆ์„ฑ, U+1161๋ถ€ํ„ฐ U+11A7๊นŒ์ง€๋Š” ์ค‘์„ฑ, U+11A8๋ถ€ํ„ฐ U+11FF๊นŒ์ง€๋Š” ์ข…์„ฑ

์œ ๋‹ˆ์ฝ”๋“œ ์ •๊ทœํ™”(Unicode equivalence)

์œ ๋‹ˆ์ฝ”๋“œ ์ •๊ทœํ™”(Unicode equivalence)๋ž€ ์ด๋ ‡๊ฒŒ ์—ฐ์†์ ์ธ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„ํ•œ ์–ด๋–ค ๊ธ€์ž๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃจ๋Š” ๋ช…์„ธ์ด๋‹ค.

  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ์œ ๋‹ˆ์ฝ”๋“œ ์ •๊ทœํ™” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ex) Swift UnicodeScalar, Swift String ๋ฌธ์„œ
  • ๋‹ค๋งŒ ์‚ฌ์šฉ์ž์˜ ํ™˜๊ฒฝ์ด ๊ฐ์ž ๋‹ค๋ฅด๊ณ  ์—„์ฒญ๋‚˜๊ฒŒ ๋‹ค์–‘ํ•˜๋ฏ€๋กœ ์ˆ˜๋งŽ์€ ์ธ์ฝ”๋”ฉ๊ณผ ๋งˆ์ฃผ์น  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.
  • (์ „๋ฐ˜์ ์œผ๋กœ ๋ณด์ž๋ฉด ์›น์˜ ๊ฒฝ์šฐ์—)์–ด๋”˜๊ฐ€์—์„œ ํ•œ๊ธ€์ด ๊นจ์ง„๋‹ค๋ฉด, ๊ทธ ์ด์œ ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ธ์ฝ”๋”ฉ ๊ฐ’๊ณผ ์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์— ์žˆ๋‹ค.
  • (Tomcat์—์„œ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ธ์ฝ”๋”ฉ ๋ฐ ํ‚ค์™€ ๊ฐ’์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด org.apache.catalina.connector.Request.parseParameters ๋ฉ”์„œ๋“œ์™€ org.apache.tomcat.util.http.Parameters.processParameters ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.)
  • ์ธ์ฝ”๋”ฉ์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์„ค์ •๋˜๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ž˜๋ชป๋œ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.
  • ์›น์—์„œ ์—ฌ๋Ÿฌ ์ธ์ฝ”๋”ฉ์„ ์ง€์›ํ•˜๋ ค๋ฉด, ์ธ์ฝ”๋”ฉ๋œ URL ๋ฌธ์ž์—ด๊ณผ ์‚ฌ์šฉํ•œ ์ธ์ฝ”๋”ฉ ์ •๋ณด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ ํ•ด์•ผ ํ•œ๋‹ค.

TIL_20180618 ~ 20180623

|

2018.06.18

2018.06.19

  • ์ฃผ์†Œ๋ก ์•ฑ ๋ฏธ์…˜ํšŒ๊ณ ํ•˜๊ธฐ
  • ์ฃผ์†Œ๋ก ์•ฑ ๋ฏธ์…˜ ๊นƒํ—™ ์ด์Šˆ์— ํ”ผ๋“œ๋ฐฑ๊ณผ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ •๋ฆฌํ•˜๊ธฐ ok
  • ์›น์•ฑ ๋ฏธ์…˜ ์‹œ์ž‘! ok
  • ์˜คํ† ๋ ˆ์ด์•„์›ƒ Safe Area: Positioning Content Relative to the Safe Area
  • Cocoapod ์‚ฌ์šฉ ok
  • swiftLint์ ์šฉ ๋ฐ ์„ค์ •๋ณ€๊ฒฝ
  • UIPresentationController

  • ์ฃผ์†Œ๋ก ์…€ํ”„ํšŒ๊ณ ๋ฆฌ์ŠคํŠธ
    • ํ…Œ์ด๋ธ”๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ํ…Œ์ด๋ธ”๋ทฐ ๋ฐ์ดํ„ฐ์†Œ์Šค์™€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋™์ž‘.
  • ์ผ๋ฐ˜ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ์„œ๋ธŒํด๋ž˜์‹ฑํ•˜์—ฌ(UITableViewController, UITableViewDelegate์™€ UITableViewDataSource ๊ตฌํ˜„) ํ…Œ์ด๋ธ”๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • UITableViewDelegate: ์„น์…˜, ํ—ค๋”๋‚˜ ํ’‹ํ„ฐ, ์…€์„ ์ง€์šฐ๊ฑฐ๋‚˜ ์žฌ์ •๋ ฌ, ์…€ ์„ ํƒ์— ๋Œ€ํ•œ ์„ค์ • ๋‹ด๋‹น
  • UITableViewDataSource: ์•ฑ์˜ ๋ฐ์ดํ„ฐ๋ชจ๋ธ๊ณผ ํ…Œ์ด๋ธ”๋ทฐ์˜ ์ค‘์žฌ๋ฅผ ๋‹ด๋‹น. DataSource ์˜ ํ…Œ์ด๋ธ”๋ทฐ์— ํ‘œ์‹œ๋  ๋ฐ์ดํ„ฐ์— ๊ด€๋ จ๋œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณต.
  • ์ปค์Šคํ…€ ์…€์€ ์„œ๋ธŒ๋ทฐ๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ์…€์— ๋‚ด์šฉ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์…€์€ reusable
  • ์…€ ๋†’์ด ์ง€์ •์€ tableView.rowHeight ์˜ต์…˜์œผ๋กœ ๊ณ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. (๊ณ ์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ์ฝ˜ํ…์ธ  ํฌ๊ธฐ์— ๋”ฐ๋ผ์„œ ๋Š˜์–ด๋‚จ!)

2018.06.20

  • WKWebView
  • Xib vs. Storyboard vs. Code
  • Dynamic Type to Adjust Text Sizes & Fonts Automatically
  • Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
    • WKWebView() ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜๋งŒ(ํ•œ๋ฒˆ๋งŒ)๋งŒ๋“ค์–ด์ ธ์„œ load์‹œํ‚ค๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ๊ทธ๋ƒฅ ๋นˆ init์œผ๋กœ๋ผ๋„ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด์ง€๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์Œ(step2 ์ฝ”๋“œ ์ฐธ๊ณ )
    • ๋ฌธ์ œ๋Š” configuration์œผ๋กœ ์ถ”์ •!! configuration์„ค๋ช…์—์„œ ์›น๋ทฐ๊ฐ€ ์ฒ˜์Œ ์ดˆ๊ธฐํ™”๋ ๋•Œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์›น๋ทฐ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ณ (์ดˆ๊ธฐํ™”๋˜๊ณ )๋‚˜์„œ ์ด ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด์„œ ์›น๋ทฐ์˜ ์„ค์ •์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค.๋Š” ๋‚ด์šฉ์ด ์žˆ๋Š”๋ฐ ์ด ๋•Œ๋ฌธ์ธ์ง€๋„ ๋ชจ๋ฅด๊ฒ ๋‹ค.

2018.06.21

  • ์ œ์Šค์ณ์— ๋Œ€ํ•ด์„œ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๊ฒƒ
    • GestureRecognizer
    • event Loop
    • first Responder
    • ๋ทฐ ๊ฐ์ฒด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋‘ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์—ด๋ ค์žˆ์Œ
    • ๋งŒ์•ฝ ํ˜„์žฌ ๋ทฐ hierarchy์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์œผ๋ฉด ๊ทธ ๋‹ค์Œ (๋” ๋ถ€๋ชจ)์œผ๋กœ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค๊ณ  ์•Œ๊ณ ์žˆ์Œโ€ฆ
    • ์ € ์…‹์˜ ์ฐจ์ด๊ฐ€ ์ •ํ™•์ด ๋ฌด์—‡์ผ๊นŒ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”๊ฑธ๊นŒโ€ฆ..?
    • ๊ฐœ๋ฐœ์ž ๋ฌธ์„œ ์ฝ๊ณ  ์ •๋ฆฌํ•˜๊ธฐ!
    • ๊ณต๋ถ€ํ•œ ํฌ์ŠคํŒ…1, ๊ณต๋ถ€ํ•œ ํฌ์ŠคํŒ…2

2018.06.23

UITableView API๋ฌธ์„œ ๋ฒˆ์—ญ, ์ •๋ฆฌ(3) - UITableViewCell

|

์›๋ฌธ์ž๋ฃŒ - Table View Programming Guide for iOS ๋ฅผ ๋ฒˆ์—ญ, ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž์Šต์šฉ์œผ๋กœ ์ •๋ฆฌํ•œ ์ž๋ฃŒ์ด๋‹ˆ ๊ฐ€๋ณ๊ฒŒ ์ฐธ๊ณ ๋งŒํ•ด์„œ ๋ณด์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™๊ณ , ํ‹€๋ฆฐ ์ ์€ ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! :)

ํ…Œ์ด๋ธ”๋ทฐ ์…€

  • ํ…Œ์ด๋ธ”๋ทฐ๋ฅผ ์ด๋ฃจ๋Š” ๊ฐœ๋ณ„์ ์ธ ํ–‰(row)
  • UITableViewCellํด๋ž˜์Šค ์ƒ์†

UITableViewCellํด๋ž˜์Šค ์…€ ์ฝ˜ํ…์ธ ์˜ ํ”„๋กœํผํ‹ฐ

  • textLabel: (UILabel ํƒ€์ž…) ์ฃผ์ œ๋ชฉ ๋ ˆ์ด๋ธ”
  • detailTextLabel: (UILabel ํƒ€์ž…) ์ถ”๊ฐ€ ์„ธ๋ถ€ ์‚ฌํ•ญ ํ‘œ์‹œ๋ฅผ ์œ„ํ•œ ๋ถ€์ œ๋ชฉ ๋ ˆ์ด๋ธ”
  • imageView: (UIImageView ํƒ€์ž…) ์ด๋ฏธ์ง€ ํ‘œ์‹œ๋ฅผ ์œ„ํ•œ ์ด๋ฏธ์ง€๋ทฐ
  • UITableViewCell์„ ์ปค์Šคํ…€ํ•˜๋Š” ๊ฒฝ์šฐ, ๊ธฐ๋ณธ ํ”„๋กœํผํ‹ฐ์™€ ๋ณ€์ˆ˜๋ช…์ด ๊ฐ™์œผ๋ฉด ์›ํ•˜๋Š” ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ปค์Šคํ…€ ์…€ ํด๋ž˜์Šค์˜ ๋ณ€์ˆ˜๋ช…์€ ๋‹ค๋ฅด๊ฒŒ ์ง€์–ด์•ผํ•จ.
    • (imageView, textLabel, detailLabel, accessoryView ๋“ฑ์˜ ๊ธฐ๋ณธ ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„)

Configure UITableViewCell

์•„๋ž˜์˜ ๋ฆฌ์ŠคํŠธ๋“ค์„ ์„ค์ •ํ•˜์—ฌ ์…€์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ. ์…€์˜ ์š”์†Œ๋ฅผ ํŒŒ์•…ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋˜์–ด ๊ฐ€์ ธ์˜ด.

  • selectionStyleโ€”Controls the appearance of the cell when selected.
  • accessoryType and accessoryViewโ€”Allow you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in normal (nonediting) mode. For a custom view, you may provide any UIView object, such as a slider, a switch, or a custom view.
  • editingAccessoryType and editingAccessoryViewโ€”Allow you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in editing mode. For a custom view, you may provide any UIView object, such as a slider, a switch, or a custom view.
  • showsReorderControlโ€”Specifies whether it shows a reordering control when in editing mode. The related but read-only editingStyle property specifies the type of editing control the cell has (if any). The delegate returns the value of the editingStyle property in its implementation of the tableView:editingStyleForRowAtIndexPath: method.
  • backgroundView and selectedBackgroundViewโ€”Provide a background view (when a cell is unselected and selected) to display behind all other views of the cell.
  • indentationLevel and indentationWidthโ€”Specify the indentation level for cell content and the width of each indentation level.

์ปค์Šคํ…€ ์…€ ๋งŒ๋“ค๊ธฐ

์…€์˜ ๋†’์ด: rowHeightํ”„๋กœํผํ‹ฐ

์…€ ๋†’์ด ๊ด€๋ จ ์ด์Šˆ

  • ์…€ ๋†’์ด๋ฅผ ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์ง€์ •ํ•ด์ฃผ์—ˆ์ง€๋งŒ ์…€์˜ ์ฝ˜ํ…์ธ (UIImageview)ํฌ๊ธฐ์— ๋”ฐ๋ผ์„œ ์…€ ๋†’์ด๊ฐ€ ๋ฐ”๋€œ
  • (์ด๋ฏธ์ง€๊ฐ€ ๋“ค์–ด๊ฐ„ ์…€์€ 80์„ ๋„˜์–ด์„œ ์ด๋ฏธ์ง€ height๋งŒํผ ์…€ ๋†’์ด๊ฐ€ ๋Š˜์–ด๋‚จ)

1. UIImageview์˜ Constraint

  • ์›์ธ: UIImageview์— ์™ผ์ชฝ ์ด๋ž‘ ์ƒ๋‹จ, ๊ฐ€๋กœ์™€ ์„ธ๋กœ๊ธธ์ด(์…€๊ณผ ๋™์ผํ•˜๋„๋ก) constraint๋ฐ–์—์•ˆ์คŒ
  • (๋ณดํ†ต view์— frame๊ฐ’ ์„ค์ •ํ•ด์ฃผ๋“ฏ์ด, ๊ทธ๊ฑธ๋กœ๋„ ์…€ ๋‚ด์—์„œ imageview ์œ„์น˜๋Š” ์žกํžŒ๋‹ค๊ณ  ๊ฐ€์ •ํ•จ)
  • ์‹œ๋„: ์•„๋ž˜๋ž‘ ์˜ค๋ฅธ์ชฝ์œ„์น˜ ๊นŒ์ง€ ์‚ฌ๋ฐฉ์„ ๋‹ค ๋ง‰์•„์•ผ ์ œ์•ฝ์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์„๊นŒ ํ•˜๊ณ  ํ•˜๋‹จ๊ณผ ์˜ค๋ฅธ์ชฝ์— constraint 0์œผ๋กœ ์คŒ

2. rowHeight์†์„ฑ์œผ๋กœ ์…€ ํฌ๊ธฐ ์ง€์ •ํ•˜๊ธฐ

  • ์œ„์—์„œ์ฒ˜๋Ÿผ ์Šคํ† ๋ฆฌ๋ณด๋“œ์˜ ์†์„ฑ์ธ์ŠคํŽ™ํ„ฐ์—์„œ ์…€์˜ ๋†’์ด๋ฅผ ์ง€์ •ํ•ด์ฃผ์—ˆ์ง€๋งŒ ๊ทธ๊ฒŒ ๋‹ค๊ฐ€ ์•„๋‹˜
    1. tableView.rowHeight = 80์ฒ˜๋Ÿผ ํ…Œ์ด๋ธ” ๋ทฐ์˜ ์…€์˜ ๋†’์ด๋ฅผ ์ง€์ •ํ•ด์ค˜์•ผํ•จ
      • You may set the row height for cells if the delegate doesnโ€™t implement the tableView(_:heightForRowAt:) method. The default value of rowHeight is automaticDimension. (์• ํ”Œ๋ฌธ์„œ ์ฐธ๊ณ )
      • ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์†Œ๋“œ์—์„œ row height์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์„๊ฑฐ๋ฉด ์œ„์˜ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ๋ฐ”๋กœ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค. ๋งŒ์•ฝ rowHeight์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์ด automaticDimension์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™ self-resizing์ด ๋œ๋‹ค.
    1. ์…€ ๋†’์ด๋ฅผ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์ง€์ •ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•: tableView(_:estimatedHeightForRowAt:) -> CGFloat
      • ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด automaticDimension๋ฅผ ๋ฆฌํ„ด ํ•˜์—ฌ ์…€์ด self-resizing๋จ
  • ๋‘ ๋ฐฉ๋ฒ•์˜ ์ฐจ์ด์  : ์„ฑ๋Šฅ ์ฐจ์ด
    • There are performance implications to using tableView(_:heightForRowAt:) instead of rowHeight. Every time a table view is displayed, it calls tableView(_:heightForRowAt:) on the delegate for each of its rows, which can result in a significant performance problem with table views having a large number of rows. (์• ํ”Œ๋ฌธ์„œ ์ฐธ๊ณ )
    • tableView.rowHeight์„ ์ „๋ถ€ ๋‹ค ์„ธํŒ…ํ•ด์ฃผ๋Š” ๊ฒƒ ๋ณด๋‹ค, ์…€์ด ํ•˜๋‚˜ ๊ทธ๋ ค์งˆ๋•Œ๋งˆ๋‹ค ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์…€์˜ ๋†’์ด๋ฅผ ๋ฆฌํ„ด๋ฐ›์•„์„œ ์„ค์ •ํ•˜๋Š”๊ฒƒ์ด ๋” ์„ฑ๋Šฅ์ƒ ๋น„ํšจ์œจ์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ํ…Œ์ด๋ธ”๋ทฐ์˜ ์…€์ด 1000๊ฐœ์ •๋„ ๋œ๋‹ค๋ฉด ๊ทธ ์„ฑ๋Šฅ ๋ฌธ์ œ๋Š” ๋”์šฑ ์‹ฌ๊ฐํ•ด์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ.
์ฐธ๊ณ ์ž๋ฃŒ