十一、Tweak(二)
2018-12-10 本文已影响51人
Lovell_
需求一:去掉《段友app》首页的广告
思路:从数据源(dataSource)入手,把广告数据删除
大致步骤:
- APP脱壳导出头文件;
- 目标cell->tableView->dataSource->adMode->init方法返回nil。
用Reveal找到广告cell,从Reveal中拿到该cell对应的TableView的内存地址,再用MJTool打印出该TableView的数据源对象#0x1460cf800.dataSource
,在数据源对象(或其父类)中找到数据源(是个可变数组),打印出来看看(#0x14689de00.feeds
或#0x14689de00->_feeds
),确定是数据源,再找出哪个是广告数据模型(疑是DYFeedAdert
),hook掉里面adView的set方法,这是方法之一; - 创建Tweak项目,编写代码,编译打包安装;
记录一些调试的技巧:打印
- 打印内存中属性或变量中的数据:通过Reveal或MJTool拿到对象的内存地址,用->来访问打印,结果显示在终端中;
- 打印方法中参数的值:NSLog(@"arg1: %@", arg1),在方法中打印形参的数据,结果显示在控制台中;
- 如果当前类没有注意查看父类中是否有;
- %c()的使用,生成一个class对象。
使用场景:需要使用到原有代码中存在的类。
if ([cell isKindOfClass:%c(DYFeedAdertCell)]){ }
替代:
if ([cell isKindOfClass:[DYFeedAdertCell class]]){ }
而不建议Tweak中声明再使用DYFeedAdertCell,这样会覆盖掉原有的类:
@interface DYFeedAdertCell : UITableViewCell
@end
@implementation DYFeedAdertCell
@end
- 给特定的view设置背景颜色,便于调试、区别。
思路总结
一、从数据源入手:
1.1 找到广告数据模型,其init方法返回nil;(本次使用的方法,此法有可能报错,如果数组添加nil没做处理的话)
1.1.1 方法
%hook DYFeedAdert
- (void)setAdView:(id)arg1{
arg1 = nil;
%orig;
}
%end
1.1.2 方法
%hook GDTNativeExpressAdView
- (id)initWithSize:(struct CGSize)arg1 positionId:(id)arg2 threadId:(id)arg3 traceId:(id)arg4 {
return nil;
}
%end
1.2 找到广告数据模型,从数据源中删除掉,好处是不会产生数组添加nil报错的问题
因为方法未声明报的错:方法名没有找到,方法找不到
Tweak.xm:39:32: error: instance method '-feeds' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access]
NSMutableArray *array = [self feeds];
^~~~~
Tweak.xm:33:32: note: receiver is instance of class declared here
@class DYFeedAdertCell; @class DYFeedsViewController;
^
1 error generated.
解决方法:声明下
// 此用来声明方法
@interface MJMethodSet
-(id)feeds;
@end
Tweak代码:hook numberOfRowsInSection:方法,在刷新数据之前,从数据源中移除广告数据。
%hook DYFeedsViewController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray *dataList = [self feeds];
NSMutableArray *adArray = [NSMutableArray array];
for (int i = 0; i < [dataList count]; ++i)
{
id mode = dataList[i];
if ([mode isKindOfClass:%c(DYFeedAdert)])
{
[adArray addObject:mode];
}
}
[dataList removeObjectsInArray:adArray];
return %orig;
}
%end
1.3
二、从cell高度入手
2.1 如果是广告cell,高度设置为1;
@interface MJMethodSet
// 用来声明方法
-(id)feeds;
@end
%hook DYFeedsViewController
// 从cell高度入手
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *dataList = [self feeds];
for (int i = 0; i < [dataList count]; ++i)
{
id mode = dataList[i];
if ([mode isKindOfClass:%c(DYFeedAdert)])
{
return 1;
}
}
return %orig;
}
%end
实际情况这样写,app会卡,而且突然回到广告cell。
最好的方法是网络请求数据下来后,把广告数据删掉,这个会面会做到。
需求二:删掉刷新按钮
%hook DYHomeRefreshButton
- (id)init {
return nil;
}
%end
搞定。