十一、Tweak(二)

2018-12-10  本文已影响51人  Lovell_

需求一:去掉《段友app》首页的广告

思路:从数据源(dataSource)入手,把广告数据删除

大致步骤:

  1. APP脱壳导出头文件;
  2. 目标cell->tableView->dataSource->adMode->init方法返回nil。
    用Reveal找到广告cell,从Reveal中拿到该cell对应的TableView的内存地址,再用MJTool打印出该TableView的数据源对象#0x1460cf800.dataSource,在数据源对象(或其父类)中找到数据源(是个可变数组),打印出来看看(#0x14689de00.feeds#0x14689de00->_feeds),确定是数据源,再找出哪个是广告数据模型(疑是DYFeedAdert),hook掉里面adView的set方法,这是方法之一;
  3. 创建Tweak项目,编写代码,编译打包安装;
记录一些调试的技巧:打印
  1. 打印内存中属性或变量中的数据:通过Reveal或MJTool拿到对象的内存地址,用->来访问打印,结果显示在终端中;
  2. 打印方法中参数的值:NSLog(@"arg1: %@", arg1),在方法中打印形参的数据,结果显示在控制台中;
  3. 如果当前类没有注意查看父类中是否有;
  4. %c()的使用,生成一个class对象。
    使用场景:需要使用到原有代码中存在的类。
if ([cell isKindOfClass:%c(DYFeedAdertCell)]){ }
替代:
if ([cell isKindOfClass:[DYFeedAdertCell class]]){ }

而不建议Tweak中声明再使用DYFeedAdertCell,这样会覆盖掉原有的类:

@interface DYFeedAdertCell : UITableViewCell
@end
@implementation DYFeedAdertCell
@end
  1. 给特定的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

搞定。

上一篇下一篇

猜你喜欢

热点阅读