2017-10-23 19:53:48 qq_18738333 阅读数 6209
  • javascript零入门实战系列

    本套javascript从入门开始,课程采用大量案例讲解js在网站中的应用. 案例主要有大量的逻辑训练题,常见的网站特效,轮播,手风琴,选项卡,键盘控制物体运动,图片透明度,缓存运动,面向对象&闭包的应用等等

    31540 人正在学习 去看看 吴华

国庆后lucio开始由Android开发转做iOS开发了,在这之前lucio可是什么苹果产品都没用过的小白,这里po一下小白的iOS开发学习历程,包括看的书、视频、文章,看看lucio如何从小白快速(并不快┓( ´∀` )┏其实)入门iOS开发的。

1. Objective-C语言入门

《Objective-C基础教程》,很好。这里整理下后面几章的学习笔记,方便复习。

《Objective-C基础教程》第8章 Foundation Kit介绍

《Objective-C基础教程》第9章 内存管理

《Objective-C基础教程》第10章 对象初始化

《Objective-C基础教程》第11章 属性

《Objective-C基础教程》第12章 类别

《Objective-C基础教程》第13章 协议

《Objective-C基础教程》第14章 代码块和并发性

2. iOS开发入门

(1) 斯坦福白胡子老头iOS8视频

斯坦福大学公开课:iOS 8开发

这个公开课每个iOS版本都有,基本是用一个demo来讲解iOS开发,每个版本的demo都不一样,iOS7是用Objective-C的,我也是看完了才知道,但看iOS8的课程也是能同步用Objective-C完成demo的,两边的方法名称完全一样,只有语法的不同。

贴一下里面关于MVC模式的讲解

MVC模式

  1. Model与View不能通信:Model与UI完全独立,UI组件都是generic的,需要Controller为其翻译并格式化Model的信息用于显示。
  2. Controller->View:View里的UI组件以outlet形式存在于Controller中。
  3. View->Controller:Controller自己注册target,告诉View当有指定的action(如按钮点击)发生时,发送这个action给我这个target。View通过delegate将should、will、did等动作的响应交给Controller处理。View不拥有其显示的数据,它是通过data source(也算一种特殊的delegate)从Controller那里拿数据,而数据来自Model。
  4. Model->Controller:Model将自己的属性变化通过广播发送给感兴趣的订阅者(一般是Controller),Notification & KVO,然后Controller去Model中取新的数据。

mvc

(2) 《疯狂iOS讲义》

看随书的源码可以快速了解各种控件的使用,以及图形、动画相关知识。

3. 阅读与思考

Part 1 - 代码规范

(1) 代码风格

Round 1 - Raywenderlich.com官方代码风格指南 :]

The official raywenderlich.com Objective-C style guide.

中文翻译:http://blog.it985.com/10771.html

需要多注意里面一些细节的东西:

  1. copy和strong的选择:把一个对象赋值给一个属性变量,当这个对象变化了,如果希望属性变量变化就使用strong属性,如果希望属性变量不跟着变化,就是用copy属性。
  2. 推荐使用代码提示中宏定义的NS_ENUM()枚举模块来创建,它可以提供更严谨的类型检测和代码补完功能。
  3. 私有变更应该在类的私有类别中,不需要加private等词语来进行修饰。
  4. 私有类别可以在命名为<headerfile>+Private.h的文件里提供。
  5. init方法中返回值使用instancetype取代id作为返回。[原因]
  6. 单例必须线程安全。
  7. :]
Round 2 - 总结自己的View层的组织规范

总结一套自己的View代码规范,日后需要慢慢完善。

// 通用viewController/view代码结构

 #pragma mark - LifeCycle Menthod
 - (void)viewDidLoad {
     [super viewDidLoad];
     [self initView()];
     [self initData()];
 }

 - (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
 }

 - (void)didReceiveMemoryWarning {
     [super didReceiveMemoryWarning];
 }

 - (instancetype)init {}
 - (void)dealloc {}

 #pragma mark - Delegate Menthod

 #pragma mark - Event response
 - (void)xxxClick(){
 }

 #pragma mark - Public

 #pragma mark - Private
 - (void)initView{
     //DO initView
     [self initConstrains()];
 }

 - (void)initConstrains{
     //DO initConstrains
 }

 - (void)initData{
     //DO initData
 }

 #pragma mark - getter && setter

 // 1. 属性(特别是View)的初始化放在getter,在initView里面只addSubview。
 // 2. 关于第1点的lazy initialization,对于需要判空的,线程不安全的以及自动优化相关的属性需要多加考虑。
 // 3. initConstrains用于初始化约束,尽量使用makeConstraints,如果约束需要动态更新,重写updateViewConstraints或updateConstraints

关于注释第2点:

Round 3 - 惰性初始化的优劣

Good or bad practice? Initializing objects in getter

lazy initialization,对于需要判空的,线程不安全的以及自动优化相关的属性需要多加考虑,原因如上。

(2) iOS工程的目录结构

Round 1 - iOS项目工程及目录结构

iOS项目工程及目录结构

区分不同层次的通用组件。

  • General Level, 最通用的组件,可以在不同项目里复用。
  • Project Level, 可以在该项目里复用。
  • Section Level, 可以在某个功能模块里复用。
Round 2 - 参考例子

iOS 项目的目录结构能看出你的开发经验

两个例子可以大概参考下。

Part 2 - 第三方库

(1) iOS开发的包管理

CocoaPods

CocoaPods安装和使用教程

Carthage

Carthage 包管理工具,另一种敏捷轻快的 iOS & MAC 开发体验

CoaoaPods 是一套整体解决方案,我们在 Podfile 中指定好我们需要的第三方库。然后 CocoaPods 就会进行下载,集成,然后修改或者创建我们项目的 workspace 文件,这一系列整体操作。

相比之下,Carthage 就要轻量很多,它也会一个叫做 Cartfile 描述文件,但 Carthage 不会对我们的项目结构进行任何修改,更不多创建 workspace。它只是根据我们描述文件中配置的第三方库,将他们下载到本地,然后使用 xcodebuild 构建成 framework 文件。然后由我们自己将这些库集成到项目中。Carthage 使用的是一种非侵入性的哲学。

(2) 常用的第三方库

Masonry

Masonry是一个轻量级的布局框架 拥有自己的描述语法 采用更优雅的链式语法封装自动布局 简洁明了 并具有高可读性 而且同时支持 iOS 和 Max OS X Masonry介绍与使用实践

AFNetworking

AFNetWorking一款轻量级网络请求开源框架,基于iOS和mac os 网络进行扩展的高性能框架 IOS 网络请求之 AFNetWorking 3.x 使用

FMDB

FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API [iOS]数据库第三方框架FMDB详细讲解 FMDB 使用方法

libextobjc

libextobjc一个提供语言级别各种小功能的库

FLEX 应用内调试神器

SDWebImage 图片加载框架

Reachability 检测手机网络状态

MJRefresh 下拉刷新,上拉加载更多组件

Toast Toast

MBProgressHUD 半透明提示框

DateTools 用于提高Objective-C中日期和时间相关操作的效率 DateTools使用「日期工具库」

更多:

iOS开发常用三方库、插件、知名博客等等

iOS 第三方库、插件、知名博客总结

Part 3 - 技巧篇

(1) 自动布局

Round 1 - UIScrollview与Autolayout

UIScrollview与Autolayout

scrollView比较特殊,因为它有个contentSize的属性。ScrollView的contentSize的大小是由其subview的constraints来决定的。

为了正常显示,使用一个单一的containerView占满全部,然后把所有的subview添加到containerView中。(亲测)

Round 2 - 约束代码何处安放

Where should I be setting autolayout constraints when creating views programmatically?

How to Use updateConstraints?

updateViewConstraints与updateConstraints可以在需要更新大量约束时重写,对于只初始化一次而不需要修改的约束,写到类似于viewDidLoad的方法中比较好。

Round 3 - 一个坑

The Mystery of the +requiresConstraintBasedLayout

基于约束的布局是懒触发的,只有在添加了约束的情况下,系统才会自动调用 -updateConstraints 方法,如果把所有的约束放在 updateConstraints中,那么系统将会不知道你的布局方式是基于约束的,所以重写+requiresConstraintBasedLayout 返回YES就是明确告诉系统:虽然我之前没有添加约束,但我确实是基于约束的布局!这样可以保证系统一定会调用 -updateConstraints 方法 从而正确添加约束。

(2) weakSelf

透彻理解block中weakSelf和strongSelf

__weak __typeof(self)weakSelf = self;
[self.context performBlock:^{
    __strong __typeof(weakSelf)strongSelf = weakSelf;
    [strongSelf doSomething];
}];

当block直接或间接的被self持有时,需要weakSelf。其他情况下加weakSelf也没什么问题。

使用libextobjc库可以简化下代码:

#import "EXTScope.h"

@weakify(self)
[self.context performBlock:^{
    @strongify(self)
    [self doSomething];
}];

(3) iOS应用数据存储

iOS本地数据存取,看这里就够了

  1. XML属性列表(plist)归档
  2. Preference(偏好设置)
  3. NSKeyedArchiver归档(NSCoding)NSKeyedArchiver–对象归档
  4. SQLite3
  5. Core Data
// TODO: 2017/10/23 继续完善本文直到结束入门

When they are needed, comments should be used to explain why a particular piece of code does something. Any comments that are used must be kept up-to-date or deleted.

——The official raywenderlich.com Objective-C style guide.

(4) iOS单例模式

JAVA设计模式之单例模式

使用dispatch_once创建单例

(5) UI适配

Round 1 - ViewController的布局

ViewController的几个属性:edgesForExtendedLayout、automaticallyAdjustsScrollViewInsets、extendedLayoutIncludesOpaqueBars

http://www.jianshu.com/p/ea9e19b7d69f

http://www.jianshu.com/p/9884f13074b8

Round 2 -如何做好IOS View的布局

如何做好IOS View的布局

  • 如何布局UIViewController的view
  • childViewController的处理
  • Autolayout来布局
  • tableView管理

布局原则:

  • 屏幕尺寸变化时能自适应,如不同尺寸设备,屏幕旋转,热点,电话等。
  • 无论是否有navigationBar或tabBar都能够正常显示,且最好不需要自己去判断有没有navigationBar或tabBar
  • 尽量避免hard code间距,如20,44,49等

(6) Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法

《Effective Objective-C 2.0:编写高质量iOS与OS X代码的52个有效方法》阅读笔记

// TODO: 2017/10/25 不再更新,之后学到的知识单独分类整理  
2019-01-09 14:58:55 Bolted_snail 阅读数 1821
  • javascript零入门实战系列

    本套javascript从入门开始,课程采用大量案例讲解js在网站中的应用. 案例主要有大量的逻辑训练题,常见的网站特效,轮播,手风琴,选项卡,键盘控制物体运动,图片透明度,缓存运动,面向对象&闭包的应用等等

    31540 人正在学习 去看看 吴华

简介

  • 最近公司研发了一个语音识别的框架,但这个框架是后端识别,所以需要手机端录音,录音后将音频文件通转成NSData类型,然后通过bsae64转码传给后台进行语音识别,识别的文字再传回给前端,虽然我认为这样做体验并不好,毕竟请求是耗时的,并且iOS10以后,自带语音识别框架,但毕竟是公司研发的框架,所以就配合做了一下测试。
  • iOS录音和音频播放用到时AVFoundation.h框架中的,AVAudioRecorder类和AVAudioPlayer,其中AVAudioPlayer播放器只能播放本地音频文件,如果要在线播放需要用AVPlayer,其配合AVPlayerLayer类还可实现视频播放。另外支持播放进度监听。

AVAudioRecorder录音

  • AVAudioRecorder录音的主要步骤:
  1. 创建录音文件保存路径,并设置相关属性(是一个字典),然后实例化AVAudioRecorder录音对象,该对象必须是全局变量
  2. 使用AVAudioSession的单例对象(音频会话对象)来设置当前音频会话状态和会话类别。
  3. 录音对象设置开始录音,录音结束后会调用录音完成的代理方法。
  • 相关代码
//导入头文件
#import <AVFoundation/AVFoundation.h>
#import "GTMBase64.h"

@interface ViewController ()<AVAudioRecorderDelegate,AVAudioPlayerDelegate>{
    NSURL * recordUrl;
    AVAudioRecorder * audioRecorder;//必须为全局变量
    AVAudioPlayer * player;//必须为全局变量
    }


//开始录音
- (void)startRecord
{
    //删除上次生成的文件,保留最新文件
    NSFileManager *fileManager = [NSFileManager defaultManager];
    //默认就是wav格式,是无损的
    if ([fileManager fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]]) {
        [fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"] error:nil];
    }
    //录音设置
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真
    [recordSetting setValue:[NSNumber numberWithFloat:16000] forKey:AVSampleRateKey];
    //录音通道数 1 或 2 ,要转换成mp3格式必须为双通道
    [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
    //线性采样位数 8、16、24、32
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    //录音的质量
    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
    // 设置录制音频采用高位优先的记录格式
    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsBigEndianKey];
    // 设置采样信号采用浮点数
    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsFloatKey];
    //存储录音文件
    NSURL * recordUrl = [NSURL URLWithString:[NSTemporaryDirectory()stringByAppendingPathComponent:@"recordAudio.wav"]];
    //初始化录音对象
    NSError * error;
    audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];
    if (error) {
        NSLog(@"%@",error.description);
        return;
    }
    audioRecorder.delegate = self;
    //开启音量检测
    audioRecorder.meteringEnabled = YES;
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象
    //如果不是正在录音
    if (![audioRecorder isRecording]) {
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
        [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.
        [audioRecorder prepareToRecord];//准备录音
        [audioRecorder record];//开始录音
        //暂停录音
//        [audioRecorder pause];
    }
}
 
 //结束录音
- (void)endRecord
{
    [audioRecorder stop];             //录音停止
}

//录音结束后代理
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放
    if (!flag) return;
    //请求接口传给后台
    [self postwavdata];
}

  • 注意:

    1. 录音时音频文件类型后缀必须为.caf、.aif、.wav中的一种,不能是.mp3,但播放是可以播放.mp3文件,可以导入githu上的一个C语言框架lame转成mp3音频文件。
    2. 将音频文件转成NSData然后用bsae64加密传给服务器,用系统自带的base64EncodedStringWithOptions编码方法后台可能解析有问题,主要是有空格和换行,可以多encode一次转义去掉这些特殊符号,也可以用第三方框架GTMBase64,请求数据时候requestContent-Type要设置为application/json,否则后台可能结束不到音频转码后端参数。
    //设置request的Content-Type为application/json
     [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    //转成base64编码格式上传服务器
    -(NSString *)wavToBASE64{
    NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];
    NSString * encodedImageStr = [GTMBase64 encodeBase64Data:wavData];
    }
    

AVAudioPlayer播放音频文件。

  • AVAudioPlayer播放音频文件主要步骤:
    1. 获取音频文件URL或者音频文件数据;
    2. 初始化AVAudioPlayer音频播放器全局对象
    3. 设置相关属性,并播放文件。
  • 相关代码
//开始播放音频文件
- (void)playWav{
//获取音频文件url
//   NSURL * url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];
//获取录音数据
NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];
NSError * error;
//    AVAudioPlayer * player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
   player = [[AVAudioPlayer alloc]initWithData:wavData error:&error];
   player.delegate = self;
   if (error) {
       NSLog(@"语音播放失败,%@",error);
       return;
   }
    //播放器的声音会自动切到receiver,所以听起来特别小,如果需要从speaker出声,需要自己设置。
   [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
   // 单独设置音乐的音量(默认1.0,可设置范围为0.0至1.0,两个极端为静音、系统音量):
   player.volume = 1.0;
//    修改左右声道的平衡(默认0.0,可设置范围为-1.0至1.0,两个极端分别为只有左声道、只有右声道):
   player.pan = -1;
//    设置播放速度(默认1.0,可设置范围为0.5至2.0,两个极端分别为一半速度、两倍速度):
   player.rate = 2.0;
//    设置循环播放(默认1,若设置值大于0,则为相应的循环次数,设置为-1可以实现无限循环):
   player.numberOfLoops = 0;
//    player.currentTime = 0;
   //调用prepareToPlay方法,这样可以提前获取需要的硬件支持,并加载音频到缓冲区。在调用play方法时,减少开始播放的延迟。
   [player prepareToPlay];
//    开始播放音乐:
   [player play];
   
   }
//播放完成代理
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
   if (flag) {
       NSLog(@"停止播放");
       //调用pause或stop来暂停播放,这里的stop方法的效果也只是暂停播放,不同之处是stop会撤销prepareToPlay方法所做的准备。
       [player stop];
       player = nil;
   }
}
  • 注意AVAudioRecorderAVAudioPlayerAVPlayerLayer一定要声明成全局变量,否则录音和播放都不能成功。
2019-03-04 09:27:21 Bolted_snail 阅读数 4241
  • javascript零入门实战系列

    本套javascript从入门开始,课程采用大量案例讲解js在网站中的应用. 案例主要有大量的逻辑训练题,常见的网站特效,轮播,手风琴,选项卡,键盘控制物体运动,图片透明度,缓存运动,面向对象&闭包的应用等等

    31540 人正在学习 去看看 吴华

  • 最近公司扫描App漏洞,提出要给App做代码混淆加固,以提高反编译逆向难度。对于Android应用直接用360安全加固即可;但对于iOS应用,虽然360也提供了免费的加固方法,但前提是项目的enable bitcode必须设置为YES。但我们项目中引入的很多框架包括百度地图等并不支持enable bitcode设置为YES。如果enable bitcode设置为NO,并且是本地部署的话(企业证书),360安全加固iOS是收费的,收费标准是30万/年。其他的一些平台也是收费的。所以只能考虑自己去做了。
  • 360 iOS加固指南

自己创建脚本文件进行代码混淆

  • 混淆原理 : 代码编译阶段将符号(方法名、属性名等)替换成随机生成的字符串
  • 我们需要创建四个文件如下:
    在这里插入图片描述
    其中PrefixHeader.pch宏文件中导入CodeObfuscation.h,这样项目在编译的时候就会将CodeObfuscation.h中定义的宏及方法名替换为对应随机生成的字符串。
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
#import "CodeObfuscation.h"
#endif /* PrefixHeader_pch */

其中confuse.sh脚本文件是最重要的,是用来在程序编译的时候将func.list中的方法名替换成随机生成的字符串,并且保存在CodeObfuscation.h中。其脚本为:

TABLENAME=symbols
SYMBOL_DB_FILE="$PROJECT_DIR/CodeObfuscation/symbols"
STRING_SYMBOL_FILE="$PROJECT_DIR/CodeObfuscation/func.list"
HEAD_FILE="$PROJECT_DIR/CodeObfuscation/CodeObfuscation.h"
export LC_CTYPE=C

#维护数据库方便日后作排重
createTable()
{
echo "create table $TABLENAME(src text, des text);" | sqlite3 $SYMBOL_DB_FILE
}

insertValue()
{
echo "insert into $TABLENAME values('$1' ,'$2');" | sqlite3 $SYMBOL_DB_FILE
}

query()
{
echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
}

ramdomString()
{
openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16
}

rm -f $SYMBOL_DB_FILE
rm -f $HEAD_FILE
createTable

touch $HEAD_FILE
echo '#ifndef CodeObfuscation_h
#define CodeObfuscation_h' >> $HEAD_FILE
echo "//confuse string at `date`" >> $HEAD_FILE
cat "$STRING_SYMBOL_FILE" | while read -ra line; do
if [[ ! -z "$line" ]]; then
ramdom=`ramdomString`
echo $line $ramdom
insertValue $line $ramdom
echo "#define $line $ramdom" >> $HEAD_FILE
fi
done
echo "#endif" >> $HEAD_FILE
sqlite3 $SYMBOL_DB_FILE .dump

func.list文件就是用来存放要被混淆的方法和属性名的。如:
在这里插入图片描述
CodeObfuscation.h本身是一个空头文件,在编译过后会生成func.list添加属性和方法对应生成的随机字符串。下图是编译后CodeObfuscation.h的内容:
CodeObfuscation.h
示例:

#import "ViewController.h"
#import "NSArray+Extension.h"

@interface ViewController ()
@property (nonatomic, copy) NSString *title1;
@property (nonatomic, copy) NSString *imgsrc;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title1 = @"";
    self.imgsrc = @"";
    
    NSLog(@"%@",[NSArray getPropertiesFromClass:[self class]]);
    NSLog(@"%@",[NSArray getMethodsFromClass:[self class]]);
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (void) test{
    
}
- (void) test1{
    
}
- (void) test2{
    
}
- (void) test3{
    
}
- (void) test4{
    
}

@end

打印出运行时的属性和方法名:
在这里插入图片描述
结果可见,CodeObfuscation.h中的生成的随机字符串和真正打印出来的并不一致,这是因为每次运行时,CodeObfuscation.h都会重新生成新的随机字符串,这时替换属性和方法名的是上一次生成的随机字符串。

  • 注意事项:
    1. 属性方法名需要去重。
    2. 代码混淆后不能再上架appstore。
    3. 代码混淆不能对静态库进行混淆。
    4. 系统自带的属性和方法不能混淆,只能混淆自定义的方法和属性。
  • 具体步骤可参考:iOS代码混淆教程

iOS代码自动混淆

  • 上面的方法会有有一些问题,就是每次创建了新的属性和方法都得添加到func.list文件中,比较繁琐,不利于维护。其实我们可以让方法属性自动添加func.list中。所以我们要从.m和.h文件中抽取属性和方法了,但是如何屏蔽系统的属性和方法名,所以我们要将自己定义的属性和方法名全部添加一个前缀。
  • confuse.sh中添加新的脚本,修改后的脚本如下:
TABLENAME=symbols
SYMBOL_DB_FILE="symbols"
STRING_SYMBOL_FILE="$PROJECT_DIR/AutoScript/func.list"
CONFUSE_FILE="$PROJECT_DIR/AutoCodeConfusion"  
HEAD_FILE="$PROJECT_DIR/AutoScript/AutocodeObfuscation.h"

export LC_CTYPE=C

#取以.m或.h结尾的文件以+号或-号开头的行 |去掉所有+号或-号|用空格代替符号|n个空格跟着<号 替换成 <号|开头不能是IBAction|用空格split字串取第二部分|排序|去重复|删除空行|删掉以init开头的行>写进func.list
grep -h -r -I  "^[-+]" $CONFUSE_FILE  --include '*.[mh]' |sed "s/[+-]//g"|sed "s/[();,: *\^\/\{]/ /g"|sed "s/[ ]*</</"| sed "/^[ ]*IBAction/d"|awk '{split($0,b," "); print b[2]; }'| sort|uniq |sed "/^$/d"|sed -n "/^hj_/p" >$STRING_SYMBOL_FILE


#维护数据库方便日后作排重,一下代码来自念茜的微博
createTable()
{
echo "create table $TABLENAME(src text, des text);" | sqlite3 $SYMBOL_DB_FILE
}

insertValue()
{
echo "insert into $TABLENAME values('$1' ,'$2');" | sqlite3 $SYMBOL_DB_FILE
}

query()
{
echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
}

ramdomString()
{
openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16

}

rm -f $SYMBOL_DB_FILE
rm -f $HEAD_FILE
createTable

touch $HEAD_FILE
echo '#ifndef AutocodeObfuscation_h
#define AutocodeObfuscation_h' >> $HEAD_FILE
echo "//confuse string at `date`" >> $HEAD_FILE
cat "$STRING_SYMBOL_FILE" | while read -ra line; do
if [[ ! -z "$line" ]]; then
ramdom=`ramdomString`
echo $line $ramdom
insertValue $line $ramdom
echo "#define $line $ramdom" >> $HEAD_FILE
fi
done
echo "#endif" >> $HEAD_FILE
sqlite3 $SYMBOL_DB_FILE .dump

在这里插入图片描述
添加了收集方法的脚本后,我们不需要再手动的去添加方法到func.list中了。程序编译后会自动将hj_开头的方法添加到func.list中。


2014-09-22 15:32:47 aini9080 阅读数 11851
  • javascript零入门实战系列

    本套javascript从入门开始,课程采用大量案例讲解js在网站中的应用. 案例主要有大量的逻辑训练题,常见的网站特效,轮播,手风琴,选项卡,键盘控制物体运动,图片透明度,缓存运动,面向对象&闭包的应用等等

    31540 人正在学习 去看看 吴华




ios向上取整 ceilf()   


向下:floorf()


extern float ceilf(float);

extern double ceil(double);

extern long double ceill(long double);


extern float floorf(float);

extern double floor(double);

extern long double floorl(long double);






2015-03-07 23:25:09 wengyupeng 阅读数 5781
  • javascript零入门实战系列

    本套javascript从入门开始,课程采用大量案例讲解js在网站中的应用. 案例主要有大量的逻辑训练题,常见的网站特效,轮播,手风琴,选项卡,键盘控制物体运动,图片透明度,缓存运动,面向对象&闭包的应用等等

    31540 人正在学习 去看看 吴华

 1、类A里方法:


-(Byte*)toByte{

 

   Byte *b= (Byte*)malloc(7);     //Byte b[7];

    b[0] =16;

    b[1] =1;

    b[2] =2;

    return b;

  }



2、调用的地方


 Byte *cmdByte =[A toByte];


    

    

3、其它问题


   //Byte byte[] = {0,1,2,3,4,5,6};

   // NSData *adata = [[NSData alloc] initWithBytes:byte length:24];

   //NSData *rdata = [[NSData alloc] initWithBytes:b length:7]; 


iOS操作系统

阅读数 2162

iOS事件拦截处理

阅读数 12700

ios10权限配置

博文 来自: qq_22026331

ios安装deb文件

阅读数 2211

ios安装deb文件dekg-ipakage.deb

博文 来自: Quiet_tomcat
没有更多推荐了,返回首页