iosdc-2018-black-magic.pdf

C5fb6051a588c0b9dc308e97800098ad?s=47 hirose yudai
August 31, 2018
1.4k

 iosdc-2018-black-magic.pdf

C5fb6051a588c0b9dc308e97800098ad?s=128

hirose yudai

August 31, 2018
Tweet

Transcript

  1. J04%$ dd̈̈̈̈࣫ࠇͷຐ๏0CKFDJUWF$3VOUJNF"1*̈̈̈̈dd

  2. ࣗݾ঺հ *%CBOO[BJ ॴଐגࣜձࣾ"TPCJDB ৬ۀ&OHJOFFS ݺশελʔޤ৯ CBOO[BJ @CBOO[BJ@

  3. ࠓ೔͸ͳ͢͜ͱ ࠇຐज़✡

  4. ࠓ೔͸ͳ͢͜ͱ ࠇຐज़✡

  5. ࠓ೔͸ͳ͢͜ͱ  "TTPDJBUJWF3FGFSFODFT  .FUIPE4XJ[[MJOH  &OVNFSBUJPO.VUBUJPO)BOEMFS

  6. "TTPDJBUJWF3FGFSFODFT

  7. "TTPDJBUJWF3FGFSFODFT  PCKD@TFU"TTPDJBUFE0CKFDU  PCKD@HFU"TTPDJBUFE0CKFDU

  8. ࣮૷ͷ׬੒ܗ

  9. ࣮૷ͷ׬੒ܗ

  10. PCKD@TFU"TTPDJBUFE0CKFDU WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJE LFZ  JEWBMVF PCKD@"TTPDJBUJPO1PMJDZQPMJDZ  Sets

    an associated value for a given object using a given key and association policy. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUBTTPDJBUFEPCKFDU MBOHVBHFPCKD
  11. PCKD@TFU"TTPDJBUFE0CKFDU WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJE LFZ  JEWBMVF PCKD@"TTPDJBUJPO1PMJDZQPMJDZ  Sets

    an associated value for a given object using a given key and association policy. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUBTTPDJBUFEPCKFDU MBOHVBHFPCKD LFZͱQPMJDZΛ࢖༻ͯ͠౉ͨ͠ PCKFDUʹWBMVFΛؔ࿈͚ͮΔ
  12. PCKD@TFU"TTPDJBUFE0CKFDU WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJE LFZ  JEWBMVF PCKD@"TTPDJBUJPO1PMJDZQPMJDZ  Sets

    an associated value for a given object using a given key and association policy. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUBTTPDJBUFEPCKFDU MBOHVBHFPCKD LFZͱQPMJDZΛ࢖༻ͯ͠౉ͨ͠ PCKFDUʹWBMVFΛؔ࿈͚ͮΔ
  13. PCKD@HFU"TTPDJBUFE0CKFDU id objc_getAssociatedObject(id object, const void *key); Returns the value

    associated with a given object for a given key. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@HFUBTTPDJBUFEPCKFDU MBOHVBHFPCKD
  14. PCKD@HFU"TTPDJBUFE0CKFDU id objc_getAssociatedObject(id object, const void *key); Returns the value

    associated with a given object for a given key. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@HFUBTTPDJBUFEPCKFDU MBOHVBHFPCKD PCKFDUʹؔ࿈͍ͮͨWBMVFΛLFZΛݩʹฦ͢Ͱ
  15. ࣮૷ͷ׬੒ܗ

  16. $POW extension UICollectionView { var mainConv: Conv? { set {

    dataSource = newValue delegate = newValue newValue?.collectionView = self objc_setAssociatedObject( self, &UICollectionViewAssociatedObjectHandle.oldConvKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC ) } get { return objc_getAssociatedObject( self, &UICollectionViewAssociatedObjectHandle.oldConvKey ) as? Conv } } } IUUQTHJUIVCDPNCBOO[BJ$POWCMPCNBTUFS$POW$POW6*$PMMFDUJPO7JFX&YUFOTJPOTXJGU
  17. .FUIPE4XJ[[MJOH

  18. .FUIPE4XJ[[MJOH - طʹఆٛ͞Ε͍ͯΔϝιουͷ࣮૷ΛೖΕସ͑Δ - Swizzle Stick Ͱ͔͖ࠞͥΔ๮Β͍͠ͷͰɺ୯ޠͷΠϝʔδͱ͠ ͯ͸ͦΜͳײ͡ - https://eow.alc.co.jp/search?q=swizzle

  19. .FUIPE4XJ[[MJOH - ϝιουͷऔಘ - class_getInstanceMethod - class_getClassMethod - ೖΕସ͑Δ -

    method_exchangeImplementations
  20. ϝιουͷએݴ - (void)viewDidLoad { NSLog(@“viewDidLoad”) } - (void)_viewDidLoad { NSLog(@“_viewDidLoad”)

    }
  21. .FUIPE4XJ[[MJOHͷॲཧ Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method exchangeMethod =

    class_getInstanceMethod([self class], @selector(_viewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod);
  22. .FUIPE4XJ[[MJOHͷॲཧ Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method exchangeMethod =

    class_getInstanceMethod([self class], @selector(_viewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod);
  23. ݺΜͰΈΔ ViewController *viewController = [ViewController new]; [viewController viewDidLoad]; ྑ͍ࢠ͸Ϛωͪ͠Όμϝͩͧ

  24. ݺΜͰΈΔ ViewController *viewController = [ViewController new]; [viewController viewDidLoad]; @WJFX%JE-PBE

  25. ϝιουͷએݴ - (void)viewDidLoad { NSLog(@“viewDidLoad”) } - (void)_viewDidLoad { NSLog(@“_viewDidLoad”)

    }
  26. &YBNQMF

  27. &YBNQMF

  28. &YBNQMF - (void)viewDidLoad { [super viewDidLoad]; UIBarButtonItem *backButtonItem = [[UIBarButtonItem

    alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil] self.navigationItem.backBarButtonItem = backButtonItem; }
  29. &YBNQMF + (void)load { @autoreleasepool { Method originalMethod = class_getInstanceMethod([self

    class], @selector(viewDidLoad)); Method exchangeMethod = class_getInstanceMethod([self class], @selector(_viewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod); } }
  30. &YBNQMF + (void)load { @autoreleasepool { Method originalMethod = class_getInstanceMethod([self

    class], @selector(viewDidLoad)); Method exchangeMethod = class_getInstanceMethod([self class], @selector(_viewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod); } }
  31. ͖ͬ͞ͷ .FUIPE4XJ[[MJOHͷॲཧ Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method exchangeMethod

    = class_getInstanceMethod([self class], @selector(exchangedViewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod);
  32. &YBNQMF - (void)_viewDidLoad { UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@""

    style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = backButtonItem; [self _viewDidLoad]; }
  33. &YBNQMF - (void)_viewDidLoad { UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@""

    style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = backButtonItem; [self _viewDidLoad]; }
  34. &YBNQMF - (void)_viewDidLoad { UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@""

    style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = backButtonItem; [self _viewDidLoad]; }
  35. ˞஫ҙ఺ - (void)viewDidLoad { [super viewDidLoad]; … }

  36. 4FHVF"EEJUJPO public extension UIViewController { fileprivate func swizzling() { let

    prepareForSegue = class_getInstanceMethod(type(of: self), #selector(UIViewController.prepare)) let _prepare = class_getInstanceMethod(type(of: self), #selector(UIViewController._prepare(segue:sender:))) method_exchangeImplementations(prepareForSegue!, _prepare!) } public func performSegue(_ withIdentifier: String, closure: ((UIStoryboardSegue) -> Void)? = nil) { swizzling() self.performSegue(withIdentifier: withIdentifier, sender: SegueEventHolder(segueClosure: closure)) swizzling() } } IUUQTHJUIVCDPNCBOO[BJ4FHVF"EEJUJPOCMPCNBTUFS$MBTTFT4FHVF"EEJUJPOTXJGU
  37. &OVNFSBUJPO.VUBUJPO)BOEMFS

  38. &OVNFSBUJPO.VUBUJPO)BOEMFS - objc_enumerationMutation - objc_setEnumerationMutationHandler

  39. PCKD@FOVNFSBUJPO.VUBUJPO WPJEPCKD@FOVNFSBUJPO.VUBUJPO JEPCK  Inserted by the compiler when a

    mutation is detected during a foreach iteration. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@FOVNFSBUJPONVUBUJPO MBOHVBHFPCKD
  40. PCKD@FOVNFSBUJPO.VUBUJPO WPJEPCKD@FOVNFSBUJPO.VUBUJPO JEPCK  Inserted by the compiler when a

    mutation is detected during a foreach iteration. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@FOVNFSBUJPONVUBUJPO MBOHVBHFPCKD ҙ༁GPSFBDIͰJUFSBUJPO͍ͯ͠Δ్தͰ ഑ྻʹมߋΛՃ͑Δͱ͜ͷؔ਺ΛׂΓࠐΜͰݺͿΑ
  41. PCKD@FOVNFSBUJPO.VUBUJPO Discussion The compiler inserts this function when it detects

    that an object is mutated during a foreach iteration. The function is called when a mutation occurs, and the enumeration mutation handler is enacted if it is set up (via the objc_setEnumerationMutationHandler function). If the handler is not set up, a fatal error occurs.
  42. PCKD@FOVNFSBUJPO.VUBUJPO Discussion The compiler inserts this function when it detects

    that an object is mutated during a foreach iteration. The function is called when a mutation occurs, and the enumeration mutation handler is enacted if it is set up (via the objc_setEnumerationMutationHandler function). If the handler is not set up, a fatal error occurs. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS ͰTFUVQ͞Εͨؔ਺͕ηοτ͞Ε͍ͯͳ͔ͬͨΒ GBUBMFSSPSΛىͥ͜͢
  43. 'BUBM&SSPSͷݕূ NSMutableArray *array = @[@1, @2, @3].mutableCopy; for (NSNumber *number

    in array) { [array removeObject:number]; }
  44. 'BUBM&SSPSͷݕূ NSMutableArray *array = @[@1, @2, @3].mutableCopy; for (NSNumber *number

    in array) { [array removeObject:number]; }
  45. 'BUBM&SSPSͷݕূ 2018-08-31 00:20:49.538515+0900 iOSDC-BlackMagick[65259:1688283] *** Terminating app due to uncaught

    exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x6000000523f0> was mutated while being enumerated.' *** First throw call stack: ( 0 CoreFoundation 0x000000011085c1e6 __exceptionPreprocess + 294 1 libobjc.A.dylib 0x000000010fef1031 objc_exception_throw + 48 2 CoreFoundation 0x00000001108d004c __NSFastEnumerationMutationHandler + 124 3 iOSDC-BlackMagick 0x000000010f5ea20c -[ViewController enumerationMutation] + 556 4 iOSDC-BlackMagick 0x000000010f5e9a69 -[ViewController viewDidLoad] + 393 5 UIKit 0x0000000110e7d131 -[UIViewController loadViewIfRequired] + 1215 6 UIKit 0x0000000110ec420c -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 6 7 UIKit 0x0000000110ec44ea -[UINavigationController _startTransition:fromViewController:toViewController:] + 136 8 UIKit 0x0000000110ec561e -[UINavigationController _startDeferredTransitionIfNeeded:] + 870 9 UIKit 0x0000000110ec686c -[UINavigationController __viewWillLayoutSubviews] + 150 10 UIKit 0x000000011111ed0b -[UILayoutContainerView layoutSubviews] + 231 11 UIKit 0x000000012d7e361c -[UILayoutContainerViewAccessibility layoutSubviews] + 42 12 UIKit 0x0000000110da87a8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1515 13 QuartzCore 0x0000000116847456 -[CALayer layoutSublayers] + 177 14 QuartzCore 0x000000011684b667 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 395 15 QuartzCore 0x00000001167d20fb _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 343 16 QuartzCore 0x00000001167ff79c _ZN2CA11Transaction6commitEv + 568 17 UIKit 0x0000000110cf3269 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 141 18 CoreFoundation 0x00000001107feb0c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 19 CoreFoundation 0x00000001107e32db __CFRunLoopDoBlocks + 331 20 CoreFoundation 0x00000001107e2a84 __CFRunLoopRun + 1284 21 CoreFoundation 0x00000001107e230b CFRunLoopRunSpecific + 635 22 GraphicsServices 0x00000001159d0a73 GSEventRunModal + 62 23 UIKit 0x0000000110cd9057 UIApplicationMain + 159 24 iOSDC-BlackMagick 0x000000010f5eab0f main + 111 25 libdyld.dylib 0x00000001142b9955 start + 1 26 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException
  46. 'BUBM&SSPSͷݕূ 2018-08-31 00:20:49.538515+0900 iOSDC-BlackMagick[65259:1688283] *** Terminating app due to uncaught

    exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x6000000523f0> was mutated while being enumerated.' *** First throw call stack: ( 0 CoreFoundation 0x000000011085c1e6 __exceptionPreprocess + 294 1 libobjc.A.dylib 0x000000010fef1031 objc_exception_throw + 48 2 CoreFoundation 0x00000001108d004c __NSFastEnumerationMutationHandler + 124 3 iOSDC-BlackMagick 0x000000010f5ea20c -[ViewController enumerationMutation] + 556 4 iOSDC-BlackMagick 0x000000010f5e9a69 -[ViewController viewDidLoad] + 393 5 UIKit 0x0000000110e7d131 -[UIViewController loadViewIfRequired] + 1215 6 UIKit 0x0000000110ec420c -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 6 7 UIKit 0x0000000110ec44ea -[UINavigationController _startTransition:fromViewController:toViewController:] + 136 8 UIKit 0x0000000110ec561e -[UINavigationController _startDeferredTransitionIfNeeded:] + 870 9 UIKit 0x0000000110ec686c -[UINavigationController __viewWillLayoutSubviews] + 150 10 UIKit 0x000000011111ed0b -[UILayoutContainerView layoutSubviews] + 231 11 UIKit 0x000000012d7e361c -[UILayoutContainerViewAccessibility layoutSubviews] + 42 12 UIKit 0x0000000110da87a8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1515 13 QuartzCore 0x0000000116847456 -[CALayer layoutSublayers] + 177 14 QuartzCore 0x000000011684b667 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 395 15 QuartzCore 0x00000001167d20fb _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 343 16 QuartzCore 0x00000001167ff79c _ZN2CA11Transaction6commitEv + 568 17 UIKit 0x0000000110cf3269 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 141 18 CoreFoundation 0x00000001107feb0c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 19 CoreFoundation 0x00000001107e32db __CFRunLoopDoBlocks + 331 20 CoreFoundation 0x00000001107e2a84 __CFRunLoopRun + 1284 21 CoreFoundation 0x00000001107e230b CFRunLoopRunSpecific + 635 22 GraphicsServices 0x00000001159d0a73 GSEventRunModal + 62 23 UIKit 0x0000000110cd9057 UIApplicationMain + 159 24 iOSDC-BlackMagick 0x000000010f5eab0f main + 111 25 libdyld.dylib 0x00000001142b9955 start + 1 26 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException 5FSNJOBUJOHBQQEVFUPVODBVHIUFYDFQUJPO/4(FOFSJD&YDFQUJPO SFBTPO  $PMMFDUJPO@@/4"SSBZ.YGXBTNVUBUFEXIJMF CFJOHFOVNFSBUFE
  47. PCKD@FOVNFSBUJPO.VUBUJPO Discussion The compiler inserts this function when it detects

    that an object is mutated during a foreach iteration. The function is called when a mutation occurs, and the enumeration mutation handler is enacted if it is set up (via the objc_setEnumerationMutationHandler function). If the handler is not set up, a fatal error occurs.
  48. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJEPCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJE IBOEMFS JE  Sets the current mutation

    handler. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUFOVNFSBUJPONVUBUJPOIBOEM MBOHVBHFPCKD
  49. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJEPCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJE IBOEMFS JE  Sets the current mutation

    handler. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUFOVNFSBUJPONVUBUJPOIBOEM MBOHVBHFPCKD ҙ༁มߋ͞Εͨ࣌ͷॲཧΛTFU͢Δͥ
  50. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@"array: %@", array); } -

    (void)enumerationMutation { objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2, @3].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } }
  51. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@"array: %@", array); } -

    (void)enumerationMutation { objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } }
  52. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@"array: %@", array); } -

    (void)enumerationMutation { objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } }
  53. ϩά array: ( 2, 3 ) array: ( 3 )

  54. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@“͓ئ͍ࢮͳͳ͍Ͱʂ”); } - (void)enumerationMutation {

    objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } objc_setEnumerationMutationHandler(nil); }
  55. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@“͓ئ͍ࢮͳͳ͍Ͱʂ”); } - (void)enumerationMutation {

    objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } objc_setEnumerationMutationHandler(nil); } ௒ศར
  56. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@“͓ئ͍ࢮͳͳ͍Ͱʂ”); } - (void)enumerationMutation {

    objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } objc_setEnumerationMutationHandler(nil); } ӕͰ͢
  57. ࢖ͬͯΈͨ void function(NSMutableArray *array) { NSLog(@“͓ئ͍ࢮͳͳ͍Ͱʂ”); } - (void)enumerationMutation {

    objc_setEnumerationMutationHandler(function); NSMutableArray *array = @[@1, @2].mutableCopy; for (NSNumber *number in array) { [array removeObject:number]; } objc_setEnumerationMutationHandler(nil); } ࢧ཭໓྾ͳࢥߟɾൃݴ
  58. ࠷ޙʹ You typically don't need to use the Objective-C runtime

    library directly when programming in Objective-C. This API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging.
  59. ࠷ޙʹ You typically don't need to use the Objective-C runtime

    library directly when programming in Objective-C. This API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging. ීஈͷ։ൃͰ͋Ε͹3VOUJNF"1*࢖͏ඞཁ͕ͳ͍ ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋ ໾ཱͭΑ
  60. ࠷ޙʹ You typically don't need to use the Objective-C runtime

    library directly when programming in Objective-C. This API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging. ීஈͷ։ൃͰ͋Ε͹3VOUJNF"1*࢖͏ඞཁ͕ͳ͍ ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋ ໾ཱͭΑ
  61. ·ͱΊ - ϓϩύςΟΛੜ΍ͤΔ - ϝιουΛೖΕସ͑ΒΕΔ - ͓ئ͍ࢮͳͳ͍Ͱʂ͕දݱͰ͖Δ - ελʔ͍ͩ͘͞

  62. ͓͠·͍a ?P?