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

iosdc-2018-black-magic.pdf

hirose yudai
August 31, 2018
3.5k

 iosdc-2018-black-magic.pdf

hirose yudai

August 31, 2018
Tweet

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. "TTPDJBUJWF3FGFSFODFT

    View full-size slide

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

    View full-size slide

  8. ࣮૷ͷ׬੒ܗ

    View full-size slide

  9. ࣮૷ͷ׬੒ܗ

    View full-size slide

  10. PCKD@TFU"TTPDJBUFE0CKFDU
    WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJELFZ
    JEWBMVF PCKD@"TTPDJBUJPO1PMJDZQPMJDZ

    Sets an associated value for a given object using a
    given key and association policy.
    ެࣜυΩϡϝϯτ
    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUBTTPDJBUFEPCKFDU
    MBOHVBHFPCKD

    View full-size slide

  11. PCKD@TFU"TTPDJBUFE0CKFDU
    WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJELFZ
    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Λؔ࿈͚ͮΔ

    View full-size slide

  12. PCKD@TFU"TTPDJBUFE0CKFDU
    WPJEPCKD@TFU"TTPDJBUFE0CKFDU JEPCKFDU DPOTUWPJELFZ
    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Λؔ࿈͚ͮΔ

    View full-size slide

  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

    View full-size slide

  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Λݩʹฦ͢Ͱ

    View full-size slide

  15. ࣮૷ͷ׬੒ܗ

    View full-size slide

  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

    View full-size slide

  17. .FUIPE4XJ[[MJOH

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  23. ݺΜͰΈΔ
    ViewController *viewController = [ViewController new];
    [viewController viewDidLoad];
    ྑ͍ࢠ͸Ϛωͪ͠Όμϝͩͧ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  33. ˞஫ҙ఺
    - (void)viewDidLoad {
    [super viewDidLoad];

    }

    View full-size slide

  34. 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

    View full-size slide

  35. &OVNFSBUJPO.VUBUJPO)BOEMFS

    View full-size slide

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

    View full-size slide

  37. [email protected]
    [email protected] JEPCK

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

    View full-size slide

  38. [email protected]
    [email protected] JEPCK

    Inserted by the compiler when a mutation is detected
    during a foreach iteration.
    ެࣜυΩϡϝϯτ
    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@FOVNFSBUJPONVUBUJPO
    MBOHVBHFPCKD
    ҙ༁GPSFBDIͰJUFSBUJPO͍ͯ͠Δ్தͰ
    ഑ྻʹมߋΛՃ͑Δͱ͜ͷؔ਺ΛׂΓࠐΜͰݺͿΑ

    View full-size slide

  39. [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.

    View full-size slide

  40. [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Λىͥ͜͢

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  43. '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

    View full-size slide

  44. '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

    View full-size slide

  45. [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.

    View full-size slide

  46. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS
    WPJEPCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJE IBOEMFS

    JE


    Sets the current mutation handler.
    ެࣜυΩϡϝϯτ
    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUFOVNFSBUJPONVUBUJPOIBOEM
    MBOHVBHFPCKD

    View full-size slide

  47. PCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS
    WPJEPCKD@TFU&OVNFSBUJPO.VUBUJPO)BOEMFS WPJE IBOEMFS

    JE


    Sets the current mutation handler.
    ެࣜυΩϡϝϯτ
    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPCKFDUJWFDPCKD@TFUFOVNFSBUJPONVUBUJPOIBOEM
    MBOHVBHFPCKD
    ҙ༁มߋ͞Εͨ࣌ͷॲཧΛTFU͢Δͥ

    View full-size slide

  48. ࢖ͬͯΈͨ
    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];
    }
    }

    View full-size slide

  49. ࢖ͬͯΈͨ
    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];
    }
    }

    View full-size slide

  50. ࢖ͬͯΈͨ
    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];
    }
    }

    View full-size slide

  51. ϩά
    array: (
    2,
    3
    )
    array: (
    3
    )

    View full-size slide

  52. ࢖ͬͯΈͨ
    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);
    }

    View full-size slide

  53. ࢖ͬͯΈͨ
    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);
    }
    ௒ศར

    View full-size slide

  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);
    }
    ӕͰ͢

    View full-size slide

  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);
    }
    ࢧ཭໓྾ͳࢥߟɾൃݴ

    View full-size slide

  56. ࠷ޙʹ
    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.

    View full-size slide

  57. ࠷ޙʹ
    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*࢖͏ඞཁ͕ͳ͍
    ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋
    ໾ཱͭΑ

    View full-size slide

  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.

    ීஈͷ։ൃͰ͋Ε͹3VOUJNF"1*࢖͏ඞཁ͕ͳ͍
    ଞͷݴޠͷϒϦοδϯά΍௿ϨΠϠʔͷσόοάʹ͸ͱͯ΋
    ໾ཱͭΑ

    View full-size slide

  59. ·ͱΊ
    - ϓϩύςΟΛੜ΍ͤΔ
    - ϝιουΛೖΕସ͑ΒΕΔ
    - ͓ئ͍ࢮͳͳ͍Ͱʂ͕දݱͰ͖Δ
    - ελʔ͍ͩ͘͞

    View full-size slide

  60. ͓͠·͍a ?P?

    View full-size slide