Reputation: 573
I want to swizzle the method @property string
in UIPasteboard
:
+ (void) load {
....
[UIPasteboard jr_swizzleMethod:@selector(string) withMethod:@selector(stringSwizzle) error:nil];
[UIPasteboard jr_swizzleMethod:@selector(setString:) withMethod:@selector(setStringSwizzle:) error:nil];
....
}
When I called [[UIPasteboard generalPasteboard] setString:@"test"];
it enter my swizzle method. It works on iOS 7, iOS 8, and iOS 9. However, it failed on iOS 10.
The assembly is differnt of a test method:
- (void) pasteboradTest {
[aUIPasteboard setString:@"test"];
}
on iOS 9:
0xced0a <+0>: push {r7, lr}
0xced0c <+2>: mov r7, sp
0xced0e <+4>: sub sp, #0x8
0xced10 <+6>: movw r2, #0xa51c
0xced14 <+10>: movt r2, #0x0
0xced18 <+14>: add r2, pc
0xced1a <+16>: movw r3, #0xa2e2
0xced1e <+20>: movt r3, #0x0
0xced22 <+24>: add r3, pc
0xced24 <+26>: ldr r3, [r3]
0xced26 <+28>: movw r9, #0xbc8e
0xced2a <+32>: movt r9, #0x0
0xced2e <+36>: add r9, pc
0xced30 <+38>: movw r12, #0xc298
0xced34 <+42>: movt r12, #0x0
0xced38 <+46>: add r12, pc
0xced3a <+48>: str r0, [sp, #0x4]
0xced3c <+50>: str r1, [sp]
0xced3e <+52>: ldr.w r0, [r12]
0xced42 <+56>: ldr.w r1, [r9]
0xced46 <+60>: blx r3
0xced48 <+62>: add sp, #0x8
0xced4a <+64>: pop {r7, pc}
on iOS 10:
0x10008f78c <+0>: stp x29, x30, [sp, #-16]!
0x10008f790 <+4>: mov x29, sp
0x10008f794 <+8>: sub sp, sp, #16 ; =16
0x10008f798 <+12>: adrp x8, 9
0x10008f79c <+16>: add x8, x8, #592 ; =592
0x10008f7a0 <+20>: adrp x9, 11
0x10008f7a4 <+24>: add x9, x9, #3480 ; =3480
0x10008f7a8 <+28>: adrp x10, 12
0x10008f7ac <+32>: add x10, x10, #1776 ; =1776
0x10008f7b0 <+36>: str x0, [sp, #8]
0x10008f7b4 <+40>: str x1, [sp]
0x10008f7b8 <+44>: ldr x10, [x10]
0x10008f7bc <+48>: ldr x1, [x9]
0x10008f7c0 <+52>: mov x0, x10
0x10008f7c4 <+56>: mov x2, x8
0x10008f7c8 <+60>: bl 0x100094cb8 ; symbol stub for: objc_msgSend
0x10008f7cc <+64>: mov sp, x29
0x10008f7d0 <+68>: ldp x29, x30, [sp], #16
0x10008f7d4 <+72>: ret
Upvotes: 3
Views: 436
Reputation: 4278
UIPasteboard
become a class cluster in iOS 10. The easiest way to notice that is to stop on breakpoint in your app and perform following command in lldb:
(lldb) po [UIPasteboard generalPasteboard]
<_UIConcretePasteboard: 0x6000000087a0>
That's the reason why swizzling doesn't work - you change implementation in UIPasteboard
class, but your application invokes implementation of _UIConcretePasteboard
private subclass.
You may try to workaround this issue with following code:
+ (void) load {
// ....
[[[UIPasteboard generalPasteboard] class] jr_swizzleMethod:@selector(string) withMethod:@selector(stringSwizzle) error:nil];
[[[UIPasteboard generalPasteboard] class] jr_swizzleMethod:@selector(setString:) withMethod:@selector(setStringSwizzle:) error:nil];
// ....
}
Of course, it's not the safe way to implement swizzling for class cluster - there is no any guarantee that you will not encounter any other private UIPasteboard
subclass in runtime.
Upvotes: 4