Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iosdc-2018-black-magic.pdf

hirose yudai
August 31, 2018
3.6k

 iosdc-2018-black-magic.pdf

hirose yudai

August 31, 2018
Tweet

Transcript

  1. 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
  2. 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Λؔ࿈͚ͮΔ
  3. 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Λؔ࿈͚ͮΔ
  4. 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
  5. 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Λݩʹฦ͢Ͱ
  6. $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
  7. .FUIPE4XJ[[MJOHͷॲཧ Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method exchangeMethod =

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

    class_getInstanceMethod([self class], @selector(_viewDidLoad)); method_exchangeImplementations(originalMethod, exchangeMethod);
  9. &YBNQMF - (void)viewDidLoad { [super viewDidLoad]; UIBarButtonItem *backButtonItem = [[UIBarButtonItem

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

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

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

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

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

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

    style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = backButtonItem; [self _viewDidLoad]; }
  16. 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
  17. [email protected] WPJE[email protected] JEPCK  Inserted by the compiler when a

    mutation is detected during a foreach iteration. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@FOVNFSBUJPONVUBUJPO MBOHVBHFPCKD
  18. [email protected] WPJE[email protected] JEPCK  Inserted by the compiler when a

    mutation is detected during a foreach iteration. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@FOVNFSBUJPONVUBUJPO MBOHVBHFPCKD ҙ༁GPSFBDIͰJUFSBUJPO͍ͯ͠Δ్தͰ ഑ྻʹมߋΛՃ͑Δͱ͜ͷؔ਺ΛׂΓࠐΜͰݺͿΑ
  19. [email protected] 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.
  20. [email protected] 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Λىͥ͜͢
  21. '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
  22. '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
  23. [email protected] 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.
  24. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJEPCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJE IBOEMFS JE  Sets the current mutation

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

    handler. ެࣜυΩϡϝϯτ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUFOVNFSBUJPONVUBUJPOIBOEM MBOHVBHFPCKD ҙ༁มߋ͞Εͨ࣌ͷॲཧΛTFU͢Δͥ
  26. ࢖ͬͯΈͨ 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]; } }
  27. ࢖ͬͯΈͨ 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]; } }
  28. ࢖ͬͯΈͨ 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]; } }
  29. ࢖ͬͯΈͨ 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); }
  30. ࢖ͬͯΈͨ 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); } ௒ศར
  31. ࢖ͬͯΈͨ 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); } ӕͰ͢
  32. ࢖ͬͯΈͨ 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); } ࢧ཭໓྾ͳࢥߟɾൃݴ
  33. ࠷ޙʹ 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.
  34. ࠷ޙʹ 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*࢖͏ඞཁ͕ͳ͍ ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋ ໾ཱͭΑ
  35. ࠷ޙʹ 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*࢖͏ඞཁ͕ͳ͍ ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋ ໾ཱͭΑ