1.插值
1.Mac自带SVN
查看版本信息:
svnserve --version
2.创建代码仓库
sudo mkdir -p ~/DeskTop/SVNStore
3.初始化代码仓库
sudo svnadmin create ~/Desktop/SVNStore
4.配置SVN权限
修改SVNStore --> conf 文件夹下内容:
svnserve.conf 配置用户权限
anon-access = read
auth-access = write
password-db = passwd
authz-db = authz
解析:
代表匿名访问的时候是只读的,若改为anon-access = none代表禁止匿名访问,需要帐号密码才能访问
删除前面的注视,不要留空格
passwd 配置账号信息
[users]
deng = 123456
deng1 = 123456
解析:
在[users]下添加用户(eg:用户名=密码)
authz 配置权限
[groups]
iosdev = deng,deng1
...
[/]
@iosdev = rw
解析:
配置名为 iosdev 的用户组,组下用户为 deng,deng1(如果多个用户,用‘,’分割)
在最下面添加 [/] 表示授权目录路径访问权限, @ioddev = rw 表示给 iosdev 组 读写权限(r - 读,w - 写,rw - 读写)
如果只允许用户访问项目下Demo文件目录,则:
[/Demo]
@iosdev = rw
@iosdev 表示授权给iosdev组,不使用 @ 则表示授权给用户
5.启动svn服务
svnserve -d -r ~/Desktop/SVNStore
解析:
回直接启动配置好的 SVNStore SVN服务器 默认使用80端口
如不使用默认的端口:
svnserve -d -r ~/Desktop/SVNStore --listen-port 8080
6.使用Cornerstone等工具连接SVN
在Cornerstone中的Server: 输入为本地电脑IP地址
7.添加内容,提交
1.终端: sudo chmod -R a+w ~/Desktop/SVNStore
2.终端: 输入电脑管理员密码
即可成功提交!
参考资料:
1.Mac上搭建本地SVN仓库
前提:
iOS设备(iPhone 或者 iPad 均可)已越狱
一、工具和软件
1.PP助手Mac版
2.iOS微信App(正式) 6.6.7 - Mac PP助手下载
3.dumpcrypted - 砸壳
4.class-dump - 导出头文件
5.iOSOpenDev1.6-2 - 替换方法
6.insert_dylib - 动态注入方法
yololib - 动态注入
7.MachOView - 查看注入是否成功
8.iOS App Signer - 签名工具
二、资源和环境
1.macOS Hign Sierra 10.13.4
2.iOS11.2.1 和 iOS11.3.1
3.Xcode9.3.1
三、操作步骤
1.class-dump导出头文件
class-dump -H XXX/Payload/WeChat.app -o XXX/WeChatHeaders
2.查看 WeChatHeaders 文件夹
若文件夹中只有 CDStructures.h 文件,且文件中什么也没有,则需要砸壳;
若文件夹中包含11695个文件,则完成头文件的导出步骤;
3.未导出文件继续执行下述操作。已导出文件-传送门
4.在已越狱的iOS设备上安装软件
通过Cydia安装
OpenSSH - 实现远程登录
Cycript - 在命令行下实现与应用的交互
PP助手
5.确保iOS设备和Mac处于同一局域网中,在Mac终端输入命令:
ssh root@192.168.1.121 远程登录已越狱的iOS设备;
默认密码: alpine
iOS设备局域网IP地址:192.168.1.121
6.在越狱的iOS设备上运行微信App后,Mac终端输入命令:
ps -e | grep WeChat
解析:
此命令用于查找WeChat可执行文件的路径;
记录此可执行文件的路径A
7.通过Cycipt查找WeChat的Document路径,Mac终端输入命令:
cycript -p WeChat
解析:
此命令用于进入cycript命令状态
8.在cycript命令状态下,输入命令:
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)[0]
解析:
获取WeChat的Document路径
记录此结果后的路径B
9.将砸壳工具dumpdecrypted 拷贝到WeChat的Document目录下用于砸壳
将命令切回Mac OS X
输入: scp dumpdecrypted.dylib root@192.168.1.121:路径B(Document路径)
10.重新远程登录到iPhone,使用dumpdecrypted.dylib砸壳,具体用法:
DYLD_INSERT_LIBRARIES=/路径B(Documents路径)/dumpdecrypted.dylib 路径A(可执行文件路径)
11.出现下图表示砸壳成功
在当前路径下生成 WeChat.decrypted 文件
12.将iOS设备上生成的 WeChat.decrypted 文件拷贝到Mac上
scp WeChat.decrypted mac登录用户名@192.168.1.121:XXX/Desktop/
解析:
jingxiankeji_tao - mac登录用户名
存放将要拷贝的 WeChat.decrypted 文件路径 - XXX/Desktop/
13.检查 WeChat.decrypted 文件 是否砸壳成功
第一个cryptid 0表示armv7架构已成功,
第二个cryptid 1表示arm64未成功
理论上只要把最老的架构解密就可以了,因为新的cpu会兼容老的架构;所以这里arm64未成功不影响
14.再次远程连接iOS设备,拷贝WeChat.app待用
ssh root@192.168.1.121 远程登录已越狱的iOS设备;
默认密码: alpine
iOS设备局域网IP地址:192.168.1.121
scp -r 路径A(可执行文件路径的上一级 WeChat.app)@192.168.1.60:XXX/Desktop/
解析:
路径A - iOS设备上存放 WeChat.app 的路径
XXX/Desktop/ - 存放将要拷贝 WeChat.app 的路径
15.砸壳完成,导出 .h 文件-传送门
参考资料:
1.非越狱微信步数和红包
2.dumpdecrypted - 砸壳
3.iOSRE逆向
4.iOS微信自动抢红包-入门教程
一、navigator - 导航
1.属性
open-type - 跳转方式 默认navigate
有效值:
navigate 对应 wx.navigateTo 或wx.navigateToMiniProgram 的功能
redirect 对应 wx.redirectTo 的功能
switchTab 对应 wx.switchTab 的功能
reLaunch 对应 wx.reLaunch 的功能
navigateBack 对应 wx.navigateBack 的功能
target 在哪个目标上发生跳转,默认当前小程序
url 当前小程序内的跳转链接
delta 当 open-type 为 'navigateBack' 时有效,表示回退的层数
app-id 当target="miniProgram"时有效,要打开的小程序 appId
path 当target="miniProgram"时有效,打开的页面路径,如果为空则打开首页
extra-data 当target="miniProgram"时有效,需要传递给目标小程序的数据,目标小程序可在 App.onLaunch(),App.onShow() 中获取到这份数据
version 当target="miniProgram"时有效,要打开的小程序版本,有效值 develop(开发版),trial(体验版),release(正式版),仅在当前小程序为开发版或体验版时此参数有效;如果当前小程序是正式版,则打开的小程序必定是正式版 默认release
hover-class 指定点击时的样式类,当hover-class="none"时,没有点击态效果
hover-stop-propagation 指定是否阻止本节点的祖先节点出现点击态
hover-start-time 按住后多久出现点击态,单位毫秒 默认50
hover-stay-time 手指松开后点击态保留时间,单位毫秒 默认50
2.navigator-hover 默认为 {background-color: rgba(0, 0, 0, 0.1); opacity: 0.7;},
二、canvas - 画布
1.属性
canvas-id canvas组件的唯一标志符
disable-scroll 当在 canvas 中移动时且有绑定手势事件时,禁止屏幕滚动以及下拉刷新 默认 false
bindtouchstart 手指触摸动作开始
bindtouchmove 手指触摸后移动
bindtouchend 手指触摸动作结束
bindtouchcancel 手指触摸动作被打断 如来电提醒、弹框等
bindlongtap 手指长按500ms之后触发,触发了长按事件后进行移动不会触发屏幕的滚动
binderror 当发生错误时触发error事件,detail={errMsg:'...'}
2.tips:
canvas 标签默认300px、高度225px;
同一页面中的canvas-id不可重复,如果使用一个已用的canvas-id,该canvas标签对应的画布将被隐藏并不再正常工作。
三、开发能力
1.open-data - 微信开发数据
type 开放数据类型
groupname 拉取群名称
userNickName
userAvatarUrl
userGender
userCity
userProvince
userCountry
userLanguage
open-gid 当 type="groupName" 时生效, 群id
lang 当 type="user*" 时生效,以哪种语言展示 userInfo,有效值有:en, zh_CN, zh_TW 默认en
2.web-view - 用了承载网页的容器,自动铺满小程序页面
src webView指向的网页,需小程序管理后台配置域名白名单
bindmessage 网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。e.detail = { data }
网页内iframe的域名也需要配置到域名白名单。
开发者工具上,可以在 <web-view/> 组件上通过右键 - 调试,打开 <web-view/> 组件的调试。
每个页面只能有一个<web-view/>,<web-view/>会自动铺满整个页面,并覆盖其他组件。
<web-view/>网页与小程序之间不支持除JSSDK提供的接口之外的通信。
在iOS中,若存在JSSDK接口调用无响应的情况,可在<web-view/>的src后面加个#wechat_redirect解决。
3.ad - 广告
目前暂时以邀请制开放申请,请留意后续模板消息的通知;
参考资料:
1.导航组件
2.W3C-小程序开发文档
一、工具和软件
1.PP助手Mac版
2.iOS微信App(越狱) 6.6.7 - Mac PP助手下载
3.dumpcrypted - 砸壳
4.class-dump - 导出头文件
5.iOSOpenDev1.6-2 - 替换方法
6.insert_dylib - 动态注入方法
yololib - 动态注入
7.MachOView - 查看注入是否成功
8.iOS App Signer - 签名工具
二、资源和环境
1.macOS Hign Sierra 10.13.4
2.iOS11.2.1 和 iOS11.3.1
3.Xcode9.3.1
三、操作步骤
1.安装Mac PP助手;
2.在PP助手中下载越狱的微信app(在未连接手机的状态下在);
如果是从appstore上下载微信app,由于此时的app是经过加密的,则需要先进行砸壳;
如果是越狱的微信App,则不需要砸壳;
3.拷贝一份微信App,修改其后缀名:.ipa–>.zip,解压ZIP文件;
4.安装class-dump工具;
在命令终端输入:class-dump 可查看class-dump软件的使用命令;
5.使用class-dump指令获取微信头文件;
命令终端输入:
class-dump -H xxxx(上述步骤3中解压的WeChat文件)/Payload/WeChat.app -o xxx(新建的文件夹-用于导出微信头文件)/WeChatHeaders
eg:
class-dump -H /Users/jingxiankeji_tao/Desktop/WeChat/Payload/WeChat.app -o /Users/jingxiankeji_tao/Desktop/WeChatHeaders
6.检查头文件是否导出正确:
查看导出的头文件夹:
若CDStructures.h中无数据:
1.还需要砸壳,工具有:AppCrackr、Clutch、dumpcrypted等,推荐dumpcrypted;
2.当砸壳完毕后,使用 class-dump 仍然只导出 CDStructures.h一个文件,则可能架构选择错误,armv7对应的是iPhone5及以下的设备,arm64则是5s及以上的设备,所以微信也包含两个架构,armv7和arm64,使用如下命令:
class-dump --arch armv7 xxxx/Payload/WeChat.app -H -o xxx/WeChatHeaders
若存在11695个文件,则完成头文件的导出步骤;
7.定位相关的文件(步数或红包)
四、微信步数
1.定位于步数相关的文件
搜索头文件夹下的包含‘step’的文件
WCDeviceStepObject.h
2.分析文件方法:用Xcode打开WCDeviceStepObject.h文件
#import "MMObject.h"
@class NSMutableArray;
@interface WCDeviceStepObject : MMObject
{
...
unsigned int m7StepCount;
unsigned int hkStepCount;
...
}
...
@property(nonatomic) unsigned int hkStepCount; // @synthesize hkStepCount;
@property(nonatomic) unsigned int m7StepCount; // @synthesize m7StepCount;
...
@end
分析:
此处的两个属性get方法:判断HealthKit是否可用,并去获取其中数据;
替换两个get方法即可修改微信运动的步数;
3.使用工具iOSOpenDev替换方法
1.利用iOSOpenDev创建hook模版
打开Xcode,进入创建一个新项目的菜单中,选择iOS-->iOSOpenDev --> CaptainHookTweak
2.在代码中修改上述的两个get方法,返回想要的数值
在创建的项目XXX.mm文件中,具体修改如下:
@class WCDeviceStepObject;
CHDeclareClass(WCDeviceStepObject); // declare class
CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, m7StepCount)
{
return 20151207;
}
CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, hkStepCount)
{
return 20151207;
}
CHConstructor // code block that runs immediately upon load
{
@autoreleasepool
{
CHLoadLateClass(WCDeviceStepObject);
CHHook(0, WCDeviceStepObject, m7StepCount); // register hook
CHHook(0, WCDeviceStepObject, hkStepCount); // register hook
}
}
4.编译Xcode创建的项目ModifyStepCount
build xcode 生成 .dylib
5.用insert_dylib工具 动态库的地址注入Mach-O
insert_dylib使用方法:
用xcode打开下载的insert_dylib项目,并编译,通过Xcode中的Products下 选中insert_dylib 右键 show in Finder
将 insert_dylib 脚本拷贝到 /usr/local/bin 目录中
不放到此目录中需要使用./insert_dylib,
放在目录中后只需要使用insert_dylib
步骤:
1.先将动态库ModifyStepCount.dylib 复制到 xx/Playload/WeChat.app 中;
2.cd 到需要注入的包中:
eg: cd xxx/xxx/Desktop/WeChat/Payload/WeChat.app/
3.命令:
insert_dylib @executable_path/ModifyStepCount.dylib WeChat
4.会生成 WeChat_patched 二进制文件
Binary is a fat binary with 2 archs.
LC_CODE_SIGNATURE load command found. Remove it? [y/n] n
LC_CODE_SIGNATURE load command found. Remove it? [y/n] n
6.用MachOView 工具 查看新的动态库是否已经被注入了
File --> Open --> xxx/WeChat/Payload/WeChat.app/Wechat_patched
Fat Binary --> Executable --> Load Commands --> LC_LOAD_DYLIB(ModifyStepCount.dylib)
7.修改 WeChat_patched –>WeChat 替换原来的文件,然后和ModifyStepCount.dylib 动态库一起放入WeChat.app中
在菜单栏上 File-->Open-->xxx/Payload/WeChat.app/WeChat
8.用iOS App Signer - 工具重签名并打包
用xcode打开 iOS App Signer,选择证书和签名
可以新创建一个 个人账号生成证书 的 项目,用此证书重新签名
在iOS App Singer 上执行相关操作后生成一个IPA包,安装在手机上即可。
五、微信防撤回
#pragma mark - 微信防撤回
CHOptimizedMethod(1, self, void, CMessageMgr, onRevokeMsg, id, value1) {
}
#pragma mark - 微信步数
CHDeclareClass(WCDeviceStepObject); // declare class
CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, m7StepCount)
{
return 151207;
}
CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, hkStepCount)
{
return 151207;
}
__attribute__((constructor)) static void entry()
{
//加载CMessageMgr类
CHLoadLateClass(CMessageMgr);
//hook AsyncOnAddMsg:MsgWrap:方法
CHClassHook(2, CMessageMgr, AsyncOnAddMsg, MsgWrap);
// 微信步数 CHLoadLateClass(WCDeviceStepObject);
CHHook(0, WCDeviceStepObject, m7StepCount);
CHHook(0, WCDeviceStepObject, hkStepCount);
// 消息防撤回
CHHook(1, CMessageMgr, onRevokeMsg);
}
六、微信红包
#pragma mark - 微信红包
/**
* 插件功能
*/
static int const kCloseRedEnvPlugin = 0;
static int const kOpenRedEnvPlugin = 1;
static int const kCloseRedEnvPluginForMyself = 2;
static int const kCloseRedEnvPluginForMyselfFromChatroom = 3;
//0:关闭红包插件
//1:打开红包插件
//2: 不抢自己的红包
//3: 不抢群里自己发的红包
static int HBPliginType = 1;
#define SAVESETTINGS(key, value) { \
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); \
NSString *docDir = [paths objectAtIndex:0]; \
if (!docDir){ return;} \
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; \
NSString *path = [docDir stringByAppendingPathComponent:@"HBPluginSettings.txt"]; \
[dict setObject:value forKey:key]; \
[dict writeToFile:path atomically:YES]; \
}
//#define LOADSETTINGS(key) ({ \
//NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); \
//NSString *docDir = [paths objectAtIndex:0]; \
//if (!docDir){ return} \
//NSString *path = [docDir stringByAppendingPathComponent:@"HBPluginSettings.txt"]; \
//NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path]; \
//if(!dict){ return} \
//NSNumber *number = [dict objectForKey:key]; \
//0
//})
CHDeclareClass(CMessageMgr);
CHMethod(2, void, CMessageMgr, AsyncOnAddMsg, id, arg1, MsgWrap, id, arg2)
{
CHSuper(2, CMessageMgr, AsyncOnAddMsg, arg1, MsgWrap, arg2);
Ivar uiMessageTypeIvar = class_getInstanceVariable(objc_getClass("CMessageWrap"), "m_uiMessageType");
ptrdiff_t offset = ivar_getOffset(uiMessageTypeIvar);
unsigned char *stuffBytes = (unsigned char *)(__bridge void *)arg2;
NSUInteger m_uiMessageType = * ((NSUInteger *)(stuffBytes + offset));
Ivar nsFromUsrIvar = class_getInstanceVariable(objc_getClass("CMessageWrap"), "m_nsFromUsr");
id m_nsFromUsr = object_getIvar(arg2, nsFromUsrIvar);
Ivar nsContentIvar = class_getInstanceVariable(objc_getClass("CMessageWrap"), "m_nsContent");
id m_nsContent = object_getIvar(arg2, nsContentIvar);
switch(m_uiMessageType) {
case 1:
{
//普通消息
//红包插件功能
//0:关闭红包插件
//1:打开红包插件
//2: 不抢自己的红包
//3: 不抢群里自己发的红包
//微信的服务中心
Method methodMMServiceCenter = class_getClassMethod(objc_getClass("MMServiceCenter"), @selector(defaultCenter));
IMP impMMSC = method_getImplementation(methodMMServiceCenter);
id MMServiceCenter = impMMSC(objc_getClass("MMServiceCenter"), @selector(defaultCenter));
//通讯录管理器
id contactManager = ((id (*)(id, SEL, Class))objc_msgSend)(MMServiceCenter, @selector(getService:),objc_getClass("CContactMgr"));
id selfContact = objc_msgSend(contactManager, @selector(getSelfContact));
Ivar nsUsrNameIvar = class_getInstanceVariable([selfContact class], "m_nsUsrName");
id m_nsUsrName = object_getIvar(selfContact, nsUsrNameIvar);
BOOL isMesasgeFromMe = NO;
if ([m_nsFromUsr isEqualToString:m_nsUsrName]) {
//发给自己的消息
isMesasgeFromMe = YES;
}
if (isMesasgeFromMe)
{
if ([m_nsContent rangeOfString:@"打开红包插件"].location != NSNotFound)
{
HBPliginType = kOpenRedEnvPlugin;
}
else if ([m_nsContent rangeOfString:@"关闭红包插件"].location != NSNotFound)
{
HBPliginType = kCloseRedEnvPlugin;
}
else if ([m_nsContent rangeOfString:@"关闭抢自己红包"].location != NSNotFound)
{
HBPliginType = kCloseRedEnvPluginForMyself;
}
else if ([m_nsContent rangeOfString:@"关闭抢自己群红包"].location != NSNotFound)
{
HBPliginType = kCloseRedEnvPluginForMyselfFromChatroom;
}
SAVESETTINGS(@"HBPliginType", [NSNumber numberWithInt:HBPliginType]);
}
}
break;
case 49: {
// 49=红包
//微信的服务中心
Method methodMMServiceCenter = class_getClassMethod(objc_getClass("MMServiceCenter"), @selector(defaultCenter));
IMP impMMSC = method_getImplementation(methodMMServiceCenter);
id MMServiceCenter = impMMSC(objc_getClass("MMServiceCenter"), @selector(defaultCenter));
//红包控制器
id logicMgr = ((id (*)(id, SEL, Class))objc_msgSend)(MMServiceCenter, @selector(getService:),objc_getClass("WCRedEnvelopesLogicMgr"));
//通讯录管理器
id contactManager = ((id (*)(id, SEL, Class))objc_msgSend)(MMServiceCenter, @selector(getService:),objc_getClass("CContactMgr"));
Method methodGetSelfContact = class_getInstanceMethod(objc_getClass("CContactMgr"), @selector(getSelfContact));
IMP impGS = method_getImplementation(methodGetSelfContact);
id selfContact = impGS(contactManager, @selector(getSelfContact));
Ivar nsUsrNameIvar = class_getInstanceVariable([selfContact class], "m_nsUsrName");
id m_nsUsrName = object_getIvar(selfContact, nsUsrNameIvar);
BOOL isMesasgeFromMe = NO;
BOOL isChatroom = NO;
if ([m_nsFromUsr isEqualToString:m_nsUsrName]) {
isMesasgeFromMe = YES;
}
if ([m_nsFromUsr rangeOfString:@"@chatroom"].location != NSNotFound)
{
isChatroom = YES;
}
if (isMesasgeFromMe && kCloseRedEnvPluginForMyself == HBPliginType && !isChatroom) {
//不抢自己的红包
break;
}
else if(isMesasgeFromMe && kCloseRedEnvPluginForMyselfFromChatroom == HBPliginType && isChatroom)
{
//不抢群里自己的红包
break;
}
if ([m_nsContent rangeOfString:@"wxpay://"].location != NSNotFound)
{
NSString *nativeUrl = m_nsContent;
NSRange rangeStart = [m_nsContent rangeOfString:@"wxpay://c2cbizmessagehandler/hongbao"];
if (rangeStart.location != NSNotFound)
{
NSUInteger locationStart = rangeStart.location;
nativeUrl = [nativeUrl substringFromIndex:locationStart];
}
NSRange rangeEnd = [nativeUrl rangeOfString:@"]]"];
if (rangeEnd.location != NSNotFound)
{
NSUInteger locationEnd = rangeEnd.location;
nativeUrl = [nativeUrl substringToIndex:locationEnd];
}
NSString *naUrl = [nativeUrl substringFromIndex:[@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length]];
NSArray *parameterPairs =[naUrl componentsSeparatedByString:@"&"];
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:[parameterPairs count]];
for (NSString *currentPair in parameterPairs) {
NSRange range = [currentPair rangeOfString:@"="];
if(range.location == NSNotFound)
continue;
NSString *key = [currentPair substringToIndex:range.location];
NSString *value =[currentPair substringFromIndex:range.location + 1];
[parameters setObject:value forKey:key];
}
//红包参数
NSMutableDictionary *params = [@{} mutableCopy];
[params setObject:parameters[@"msgtype"]?:@"null" forKey:@"msgType"];
[params setObject:parameters[@"sendid"]?:@"null" forKey:@"sendId"];
[params setObject:parameters[@"channelid"]?:@"null" forKey:@"channelId"];
id getContactDisplayName = objc_msgSend(selfContact, @selector(getContactDisplayName));
id m_nsHeadImgUrl = objc_msgSend(selfContact, @selector(m_nsHeadImgUrl));
[params setObject:getContactDisplayName forKey:@"nickName"];
[params setObject:m_nsHeadImgUrl forKey:@"headImg"];
[params setObject:[NSString stringWithFormat:@"%@", nativeUrl]?:@"null" forKey:@"nativeUrl"];
[params setObject:m_nsFromUsr?:@"null" forKey:@"sessionUserName"];
if (kCloseRedEnvPlugin != HBPliginType) {
//自动抢红包
((void (*)(id, SEL, NSMutableDictionary*))objc_msgSend)(logicMgr, @selector(OpenRedEnvelopesRequest:), params);
}
return;
}
break;
}
default:
break;
}
}
七、安装iOSOpenDev失败的解决方法
先重启Xcode,在Xcode中创建新项目中,查看菜单iOS中是否存在iOSOpenDev 一项内容
1.官方解决方法
1.在点击 安装iOSOpenDev软件的失败弹框 任意地方,使其成为Mac菜单即可;
2.Command + L 显示安装日志弹框;
3.在弹框的左上角选择 "显示所有日志";
4.滚动到日志底部,查看失败原因;
5.根据原因处理问题;
2.其他解决方法
八、其他
1.iOS可执行文件位置:
一般我们得到的iOS程序包是.ipa文件。其实就是一个压缩包,解压缩.ipa。解压缩后里面会有一个payload文件夹,文件夹里有一个.app文件,右键显示包内容,然后找到一个一般体积最大跟.app同名的文件,那个文件就是可执行文件;
参考资料:
1.非越狱微信步数和红包
2.非越狱iOS微信自动抢红包
3.非越狱iOS微信自动抢红包2
4.非越狱iOS修改微信步数
5.安装iOSOpenDev失败的解决方法
6.在非越狱平台进行越狱开发
7.iOS可执行文件分析工具MachoOView
8.yololib - 动态注入
9.insert_dylib的使用方法
一、button
1.属性列表
size 按钮大小 String 默认 default
有效值: default、 mini
type 按钮的样式类型 String default
有效值:primary、default、warn
form-type 用于<form/>组件,点击分别会触发<form/>组件的submit/reset事件;
有效值:submit、reset
plain 按钮是否镂空,背景色透明 默认false
disabled 是否禁用 false
loading 名称前是否带有loading图标 false
open-type 微信开发能力 String
有效值:
contact 打开客服会话
share 触发用户转发
getUserInfo 获取用户信息,可以从bindgetuserinfo回调中获取到用户信息
getPhoneNumber 获取用户手机号,可以从bindgetphonenumber回调中获取到用户信息
launchApp 可以从bindgetphonenumber回调中获取到用户信息
openSetting 可以从bindgetphonenumber回调中获取到用户信息
hover-class 指定按钮按下去的样式类,hover-class=‘none’时,没有点击态效果 默认button-hover
...
2.tips
button-hover 默认 {background-color: rgba(0,0,0,0.1);opacity:0.7}
在bindgetphonenumber 等返回加密信息的回调中 调用wx.login登录,可能会刷新登录状态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态
3.eg:
<button type="warn" size="mini">按钮</button>
<button type="primary" loading="true">页面主操作 Loading</button>
<button type="primary" disabled="true" plain="true">不可点击的按钮</button>
...
二、checkbox - 多项选择器,内部由多个checkbox组成
1.属性
checkbox-group:
bindchange <checkbox-group/>中选中项发生改变是触发 change 事件,detail = {value:[选中的checkbox的value的数组]}
checkbox:
value <checkbox/>标识,选中时触发<checkbox-group/>的 change 事件,并携带 <checkbox/> 的 value
disabled 是否禁用 默认false
checked 当前是否选中,可用来设置默认选中 默认false
color checkbox颜色
2.eg
xx.wxml
<text>多项选择</text>
<checkbox-group bindchange="checkboxChange">
<view class='checkbox'>
<label class=' checkBox' wx:for="{{coutry}}">
<checkbox value="{{item.name}}" checked="{{item.checked}}">{{item.value}}</checkbox>
</label>
</view>
</checkbox-group>
xx.js
Page({
data: {
coutry:[
{ name: 'USA', value: '美国' },
{ name: 'CHN', value: '中国', checked: 'true' },
{ name: 'BRA', value: '巴西' },
{ name: 'JPN', value: '日本' },
{ name: 'ENG', value: '英国' },
{ name: 'TUR', value: '法国' },
]
},
checkboxchange: function(e){
console.log('checkbox发生change事件,携带value值为:',e.detail.value)
}
})
三、form
表单,将组件内的用户输入的<switch/> <input/> <checkbox/> <slider/> <radio/> <picker/> 提交。
当点击 <form/> 表单中 formType 为 submit 的 <button/> 组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key
四、input
1.属性
type input的类型 默认‘text’
有效值: text number idcard(身份证输入键盘) digit(带小数点的数字键盘)
confirm-type 设置键盘右下角按钮的文字 默认‘done’
有效值: send-发送 search-搜索 next-下一个 go-前往 done-完成
value 输入框的初始内容
password 是否是密码类型 默认false
placeholder 输入框为空时的占位符
placeholder-style 指定placeholder的样式
placeholder-class 指定placeholder的样式类
maxlength 最大输入长度 140 设置为-1时不限制最大长度
cursor-spacing 指定光标与键盘的距离单位px
focus 获取焦点 false
confirm-hold 点击键盘右下角按钮时,是否保持键盘不收起 默认false
cursor 指定focus时的光标位置
adjust-position 键盘弹起时,是否自动上推页面 默认true
bindinput 键盘输入时,触发input事件
bindfocus 输入框聚焦时触发
bindblur 输入框失去焦点时触发
bindconfirm 点击完成按钮时触发
五、label
用来改进表单组件的可用性,使用for属性找到对应的id,或者将控件放在该标签下,当点击时,就会触发对应的控件。
for优先级高于内部控件,内部有多个控件的时候默认触发第一个控件。
目前可以绑定的控件有:<button/>, <checkbox/>, <radio/>, <switch/>
六、滚动选择器
从底部弹起的滚动选择器,现支持五种选择器,通过mode来区分:
mode = selector 普通选择器 - 默认
mode = multiSelecto 多列选择器
mode = time 时间选择器
mode = date 日期选择器
mode = region 省市区选择器
1.picker - 嵌入页面的滚动选择器
2.picker-view - 嵌入页面的滚动选择器
其中只可放置<picker-view-column/>组件,其他节点不会显示;
picker-view-column:
仅可放置于<picker-view />中,其孩子节点的高度会自动设置成与picker-view的选中框的高度一致
滚动时在iOS自带振动反馈,可在系统设置 -> 声音与触感 -> 系统触感反馈中关闭
七、radio - 单项选择器,内部由多个
八、slider - 滑动选择器
九、switch - 开关选择器
十、textarea - 多行输入框
bug: 微信版本 6.3.30,textarea 在列表渲染时,新增加的 textarea 在自动聚焦时的位置计算错误。
tip:
textarea 的 blur 事件会晚于页面上的 tap 事件,如果需要在 button 的点击事件获取 textarea,可以使用 form 的 bindsubmit。
不建议在多行文本上对用户的输入进行修改,所以 textarea 的 bindinput 处理函数并不会将返回值反映到 textarea 上。
textarea 组件是由客户端创建的原生组件,它的层级是最高的,不能通过 z-index 控制层级。
请勿在 scroll-view、swiper、picker-view、movable-view 中使用 textarea 组件。
css 动画对 textarea 组件无效。
一、icon - 图标
1.属性列表
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
type | String | icon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clear,circle | |
size | Number | 23 | icon的大小,单位px |
color | Color | icon的颜色,同css的color |
2.eg:
wxml:
<view class='group'>
<block wx:for="{{iconSize}}">
<icon type="success" size="{{item}}"></icon>
</block>
</view>
<view class='group'>
<block wx:for="{{iconType}}">
<icon type="{{item}}" size="40"></icon>
</block>
</view>
<view class='group'>
<block wx:for="{{iconColor}}">
<icon type="success" size="40" color="{{item}}"></icon>
</block>
</view>
js:
Page({
data: {
iconSize: [20,30,40,50,60,70],
iconColor: [
'red','orange','yellow','green','rgb(0,255,255)','blue','purple'
],
iconType:[
'success','success_no_circle','info','warn','waiting','cancel','download','search','clear','circle'
]
}
})
二、text - 文本
1.属性列表
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
selectable | Boolean | false | 文本是否可选 |
space | String | false | 显示连续空格 |
decode | Boolean | false | 是否解码 |
2.space有效值
ensp 中文字符空格一半大小
emsp 中文字符空格大小
nbsp 根据字体设置的空格大小
3.tips:
decode可以解析的有: 、<、>、&、&apos、&ensp、 
各个操作系统的空格标准不一致;
<text/>组件内只支持<text/>嵌套;
除了文本节点以外的其他节点都无法长按选中;
4.eg:
.wxml
<view class="text-box" scroll-y="true" scroll-top="{{scrollTop}}">
<text>{{text}}</text>
</view>
<button disabled="{{!canAdd}}" bindtap="add">add line</button>
<button disabled="{{!canRemove}}" bindtap="remove">remove line</button>
.js
var texts = [
'2011年1月,微信1.0发布',
'同年5月,微信2.0语音对讲发布',
'10月,微信3.0新增摇一摇功能',
'2012年3月,微信用户突破1亿',
'4月份,微信4.0朋友圈发布',
'同年7月,微信4.2发布公众平台',
'2013年8月,微信5.0发布微信支付',
'2014年9月,企业号发布',
'同月,发布微信卡包',
'2015年1月,微信第一条朋友圈广告',
'2016年1月,企业微信发布',
'2017年1月,小程序发布',
'......'
];
Page({
data: {
text: '',
canAdd: true,
canRemove: false
},
extraLine: [],
add: function (e) {
var that = this;
this.extraLine.push(texts[this.extraLine.length % 12])
this.setData({
text: this.extraLine.join('\n'),
canAdd: this.extraLine.length < 12,
canRemove: this.extraLine.length > 0
})
setTimeout(function () {
that.setData({
scrollTop: 99999
});
}, 0)
},
remove: function (e) {
var that = this;
if (this.extraLine.length > 0) {
this.extraLine.pop()
this.setData({
text: this.extraLine.join('\n'),
canAdd: this.extraLine.length < 12,
canRemove: this.extraLine.length > 0,
})
}
setTimeout(function () {
that.setData({
scrollTop: 99999
});
}, 0)
},
})
三、rich-text - 富文本
1.属性列表
nodes 节点列表/HTML String Array/String
2.node
现支持两种节点,通过type来区分,分别是元素节点和文本节点,默认是元素节点,在富文本区域里显示的HTML节点
3.元素节点:type = node
name 标签名 必填
attrs 属性
children 子节点列表, 结构和nodes一致
4.文本节点: type = text
text 文本 String 必填
5.tips:
nodes 不推荐使用 String 类型,性能会有所下降。
rich-text 组件内屏蔽所有节点的事件。
attrs 属性不支持 id ,支持 class 。
name 属性大小写不敏感。
如果使用了不受信任的HTML节点,该节点及其所有子节点将会被移除。
img 标签仅支持网络图片。
如果在自定义组件中使用 rich-text 组件,那么仅自定义组件的 wxss 样式对 rich-text 中的 class 生效。
6.eg:
.wxml
<view>
<rich-text nodes="{{nodes}}" bindtap="tap"></rich-text>
</view>
.js
Page({
data:{
nodes: [{
name: 'div',
attrs: {
class: 'div_class',
style: 'line-height: 60px; color: red;'
},
children: [{
type: 'text',
text: 'Hello World!'
}]
}]
},
tap() {
console.log('tap')
}
})
四、progress - 进度条
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
percent | Float | 百分比0-100 | |
show-info | Boolean | false | 在进度条右侧显示百分比 |
stroke-width | Number | 6 | 进度条线的宽度,单位px |
color | Color | #09BB07 | 进度条颜色(请使用activeColor) |
activeColor | Color | 已选择进度条颜色 | |
backgroundColor | Color | 未选择进度条颜色 | |
active | Boolean | false | 进度条从左往右的动画 |
active-mode | String | backwards | backwards: 动画从头播;forwards:动画从上次结束点接着播 |
2.eg:
<view>
<progress percent='20' show-info='ture'></progress>
<progress percent='40' stroke-width='12'></progress>
<icon class="progress-cancel" type="cancel"></icon>
<progress percent='60' color='pink'></progress>
<progress percent='80' active='ture'></progress>
<progress percent='100' active-mode='backwards' ></progress>
</view>
参考资料:
1.基础组件
2.W3C-小程序开发文档
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true