通过选择联系人,添加到群,首先调用MMSessionPickerListRowView的checkboxChecked:方法。

伪代码如下:

1
2
3
4
5
6
7
8
9
10
void -[MMSessionPickerListRowView checkboxChecked:](void * self, void * _cmd, void * arg2) {
rbx = self;
if ([self disabled] == 0x0) {
rax = [rbx chosen];
[rbx setChosen:sign_extend_64(rax)];
[rbx _callDelegate];
[rbx setNeedsDisplay:0x1];
}
return;
}

重写的代码:

1
2
3
4
5
6
7
8
9
- (void) checkboxChecked: (id)arg1 {
MMSessionPickerListRowView *listRowView = (MMSessionPickerListRowView *)self;
if ([listRowView disabled] == NO) {
BOOL chosen = [listRowView chosen];
[listRowView setChosen: sign_extend_64(chosen)];
[listRowView _callDelegate];
[listRowView setNeedsDisplay:YES];
}
}

再来看看MMSessionPickerListRowView的setChosen:方法。

伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void -[MMSessionPickerListRowView setChosen:](void * self, void * _cmd, char arg2) {
r15 = self;
rbx = [[self checkbox] retain];
[rbx setState:arg2 != 0x0 ? 0x1 : 0x0];
[rbx release];
rbx = [[r15 checkbox] retain];
r12 = [rbx state];
[rbx release];
r14 = [[r15 checkbox] retain];
rdi = @class(NSImage);
rsi = @selector(imageNamed:);
if (r12 != 0x0) {
rbx = [_objc_msgSend(rdi, rsi) retain];
[r14 setImage:rbx];
}
else {
rbx = [_objc_msgSend(rdi, rsi) retain];
[r14 setImage:rbx];
}
[rbx release];
[r14 release];
rdi = r15;
[rdi setNeedsDisplay:0x1];
return;
}

重写代码:

1
2
3
4
5
6
7
8
9
10
11
12
- (void) setChosen: (char *) arg2 {
MMSessionPickerListRowView *listRowView = (MMSessionPickerListRowView *)self;
NSButton *checkbox = [listRowView checkbox];
[checkbox setState: arg2 != nil ? 1 :0];
// 下面这个if我还是没能看懂要干嘛...
if ([checkbox state]) {
[checkbox setImage:[NSImage imageNamed:nil]];
} else {
[checkbox setImage:[NSImage imageNamed:nil]];
}
[listRowView setNeedsDisplay:YES];
}

MMSessionPickerListRowView的target指向的是MMSessionListView对象,其内存地址为0x0000600000169fc0。

MMSessionPickerListRowView的action是一个选择器selector,其值为rowToggled:,内存地址为0x00000001019ae7e4。

定位MMSessionListView的rowToggled:方法,方法原型:

1
- (void) rowToggled: (id)arg1;

断掉调试,其参数是MMSessionPickerListRowView对象。也就是在MMSessionPickerListRowView对象中调用@selector(rowToggled:)的时候,传入的参数self。

追踪rowToggled:方法,发现基本逻辑都是处理视图层的业务,主要逻辑代码[rbx updateSessionChoosenView:r15->m_logic];。最后的业务处理交给我_delegate这个变量的对象。依然是通过选择器传递消息,在该_delegate对象不为空的情况下,处理其他逻辑。debug发现_delegate是MMSessionChoosenView的对象,当然如果不debug,可以从代码中发现[rbx respondsToSelector:@selector(updateSessionChoosenView:)],这段代码说明某个对象中有updateSessionChoosenView:方法,通过Hopper搜索,很快就会定位到MMSessionChoosenView类。至此,也就意味着,主要代码中rbx寄存器中的对象时MMSessionChoosenView的对象。

接下来分析MMSessionChooseView中的updateSessionChoosenView:方法,分析发现,依然是处理视图层的东西,设置颜色以及按钮是否可用等。