Fork me on GitHub

微信小程序tips

最近公司项目改版,趁产品修改与UI出图的间歇用公司商户端UI图撸了一把微信小程序。因为刚刚实习那一会接触过前端开发,所以上手还比较快,当然也遇到了很多的问题,不过好在基本按图完成。趁此总结一下我遇到的问题,奉上一些可行的解决方案,希望可以帮助与我遇到相同问题的朋友。demo

先上图

微信小程序

tips

背景图片不能使用本地的

这个问题坑了我很久,因为在模拟器上跑时,将本地图片作为View的背景图片是可以的,但是一到真机测试就不显示背景图片了,一开始还以为是路径错了,经过测试发现路径是没有问题的,最后在网上找到了原因:微信小程序的背景图片不能是本地图片,必须是是网络图片,于是我就找了一个网站将图片传了上去,将网址作为背景图片链接,就奇迹般的显示了,很是无语。

不能加载网页

微信小程序是不能跳转到网页的,也许是因为微信小程序本身就如同网页吧,也可能是微信不想有人越过它的审核,反正他是不允许直接加载网页的。

不能隐藏导航栏

我的登陆页面本来是不应该有导航栏的,可是就是隐藏不了,也许有方法,但是我找了很久也没有发现。

只支持HTTPS的网络协议并且一个月只能修改5次

在微信小程序中网络请求只能是https类型的。在添加URL的时候都已经限制死了。并且一个月只能修改5次,网络请求必须先进行服务器域名配置。

添加URL
)

所有的页面都必须在app.json中配置路径

我之前新建一个页面然后跳转过去一直报路径错误,去网上查询才知道,每一个页面路径都需要提前配置。

页面路径配置

网络请求的最大并发数为5、页面层级最多5层

就是说同时最多5个网络请求,页面的子页面最多4个。我在想要是一个页面是一个视频列表展示怎么办,每一个视频都需要网络请求啊。

以上就是这次遇到的一些比较变态的问题。

谈谈我的一些代码实现

配置tabBar(app.json)

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
26
"tabBar": {
"color": "#888888",
"selectedColor": "#09BB07",
"backgroundColor": "",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/orderManage/orderManage",
"text": "订单管理",
"iconPath": "pages/images/order.png",
"selectedIconPath": "pages/images/order_r.png"
},
{
"pagePath": "pages/moneyManage/moneyManage",
"text": "财务管理",
"iconPath": "pages/images/money.png",
"selectedIconPath": "pages/images/money_r.png"
},
{
"pagePath": "pages/myself/myself",
"text": "我的商户",
"iconPath": "pages/images/people.png",
"selectedIconPath": "pages/images/people_r.png"
}
]
}

订单管理页的菜单栏

点击菜单栏切换View简单,直接将将点击的菜单的值赋给View让其偏移对应的百分比就好。

手势切换:通过触摸的起点与终点计算出滑动方向,然后偏移并且切换菜单栏。

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
26
27
28
29
30
    catchtouchstart:function(e){
var that = this;
that.setData({
startPoint: [e.touches[0].clientX,e.touches[0].clientY]
})
},
catchtouchend:function(e){
var that = this;
var currentNum = parseInt(this.data.currentNavtab);
var endPoint = [e.changedTouches[0].clientX,e.changedTouches[0].clientY];
var startPoint = that.data.startPoint
if(endPoint[0] <= startPoint[0]) {
if(Math.abs(endPoint[0] - startPoint[0]) >= Math.abs(endPoint[1] - startPoint[1]) && currentNum< this.data.navTab.length -1) {
currentNum=currentNum + 1;
}
}else {
if(Math.abs(endPoint[0] - startPoint[0]) >= Math.abs(endPoint[1] - startPoint[1]) && currentNum > 0) {
currentNum -= 1;
}
}
this.setData({
currentNavtab: currentNum
});
},
// 点击菜单栏切换View
switchTab: function(e){
this.setData({
currentNavtab: e.currentTarget.dataset.idx
});
}

结束

整个程序还是很简单的,就是初次写还是有些不适应。尤其是把div改为了View,不能使用window对象和document对象,很不适应。再次奉上demo

项目总结-位置实时共享

从北京回来到今天已经整整三个月了,三个月没有更新简书了。回来找了一家新的公司上班,正好今天新项目打包测试了,找了点时间来总结一下最近项目中遇到的一些问题与心得。今天主要分享位置实时共享,其实之前也有时间,因为在新的公司很少加班。但是自己太懒了,所以……。

谈谈新公司

进入公司才发现公司有个iOS大神和我是一个大学的 还是一个系的 还是同一级的,还有两个Android与我是一个专业的,这个行业真的小啊😄。公司不大,老板是个美籍华人(这应该是我们加班少的原因吧)。

谈谈项目

项目内容保密(签了协议的)……,还是谈技术吧。
1>即时通讯:我们用的是环信的,因为这不是主要的功能,使用就直接用的是环信的UI,就是官方demo里面的EaseUI,导入SDK就不用说了,我主要分享一下我们在里面添加的一个新的功能:实时位置共享 我们将这个功能添加在群聊里面的。主要逻辑:是通过环信群聊的透传消息实现的用的是百度地图。

通过百度地图定位 将自己的位置的经纬度放在透传消息的扩展信息中传出去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 更新发送
- (void)sendCmdMessageWithType:(NSString *)type {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:@"shareLocation"];
_currentUserId = [[NSUserDefaults standardUserDefaults] objectForKey:@"eid"];
NSDictionary *ext = @{@"latitude":@(_userStartLocation.location.coordinate.latitude),@"longitude":@(_userStartLocation.location.coordinate.longitude),@"type":type,_currentUserId:[[NSUserDefaults standardUserDefaults] objectForKey:@"user_nickname"]};

EMMessage *message = [[EMMessage alloc] initWithConversationID:self.conversationID
from:_currentUserId
to:self.conversationID
body:body
ext:ext];
message.chatType = EMChatTypeGroupChat;
[[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *message, EMError *error) {
if (error) {
[CTHUD showText:@"位置更新失败"];
// 去请求token
}
}];
});
}

然后在解析透彻信息的解析位置信息

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
26
27
28
29
30
31
32
33
// 收到解析
- (void)didReceiveCmdMessages:(NSArray *)aCmdMessages {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (EMMessage *cmdMessage in aCmdMessages) {
EMCmdMessageBody *body = (EMCmdMessageBody *)cmdMessage.body;
// 判断是否是位置共享消息
if ([body.action isEqualToString:@"shareLocation"]) {
CLLocationCoordinate2D coordinate;
coordinate.latitude = [[cmdMessage.ext objectForKey:@"latitude"] doubleValue];
coordinate.longitude = [[cmdMessage.ext objectForKey:@"longitude"] doubleValue];
NSString *nickName = [cmdMessage.ext objectForKey:cmdMessage.from];
if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"update"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateOtherAnnotationWithLocation:coordinate UserNickName:nickName];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"remove"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self removeOtherAnnotationWithUserNickName:nickName];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"join"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addMyAnnotationWithLocation:coordinate UserNickName:nickName];
[self sendCmdMessageWithType:@"feedback"];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"feedback"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addMyAnnotationWithLocation:coordinate UserNickName:nickName];
});
}
}
}
});
}

将所有收到的透传消的位置信息标识在地图上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 添加新的用户标注
- (void)addMyAnnotationWithLocation:(CLLocationCoordinate2D)coordinate UserNickName:(NSString *)nickName{
BMKPointAnnotation *annotation = [[BMKPointAnnotation alloc]init];
annotation.coordinate = coordinate;
annotation.title = nickName;
[_mapView addAnnotation:annotation];
[_mapView selectAnnotation:annotation animated:YES];
[_otherUserAnnotation addObject:annotation];
[_otherUserNickName addObject:nickName];
[_mapView showAnnotations:_otherUserAnnotation animated:YES];
[_mapView setCenterCoordinate:coordinate animated:YES];
while (!_mapView.zoomOut) {
}
}

还需要通过传递者的传递的类型定该位置是新加入用户还是已经存在的用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"update"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateOtherAnnotationWithLocation:coordinate UserNickName:nickName];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"remove"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self removeOtherAnnotationWithUserNickName:nickName];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"join"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addMyAnnotationWithLocation:coordinate UserNickName:nickName];
[self sendCmdMessageWithType:@"feedback"];
});
}else if ([[cmdMessage.ext objectForKey:@"type"] isEqualToString:@"feedback"]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addMyAnnotationWithLocation:coordinate UserNickName:nickName];
});
}

新用户需要添加大头针,已经存在的用户只需要更新位置

1
2
3
4
5
6
7
8
// 更新用户标注
- (void)updateOtherAnnotationWithLocation:(CLLocationCoordinate2D)coordinate UserNickName:(NSString *)nickName{
for (BMKPointAnnotation *annotation in _otherUserAnnotation) {
if ([annotation.title isEqualToString:nickName]) {
annotation.coordinate = coordinate;
}
}
}

通过百度地图获得自己移动的距离

1
2
3
4
5
6
BMKMapPoint point1 = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(_userStartLocation.location.coordinate.latitude,_userStartLocation.location.coordinate.latitude));

BMKMapPoint point2 = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(userLocation.location.coordinate.latitude,userLocation.location.coordinate.latitude));

CLLocationDistance distance = BMKMetersBetweenMapPoints(point1,point2);

自己定义一个移动的精度,我们当时定的移动距离大于20米(distance>20)就发送一次位置更新。
最后当需要离开位置共享是也需要再发送一次信息,透传解析出,然后移除标识

1
2
3
4
5
6
7
8
9
10
// 删除用户标注
- (void)removeOtherAnnotationWithUserNickName:(NSString *)nickName{
for (BMKPointAnnotation *annotation in _otherUserAnnotation) {
if ([annotation.title isEqualToString:nickName]) {
[_otherUserAnnotation removeObject:annotation];
[_otherUserNickName removeObject:nickName];
[_mapView removeAnnotation:annotation];
}
}
}

结束语

实时共享 其实与群聊差不多,就是我的位置移动距离达到了精度要求,我就发送一次群消息,让每一个参加共享的人都知道,然后在自己的地图上更新一次。以上就是我们的位置实时共享的逻辑与部分代码,欢迎各位的指正,谢谢。

iOS-webView上加载HTML视频不显示缩略图

最近在项目中遇到了一个比较棘手的问题:在原生的iOS的webView上面加载HTML视频发现没有缩略图,在网上查了资料发现在HTML里面有个poster属性(添加一个图片)可以设置缩略图,但是我们的后台告诉我视频资源本来就是来自网络的,没有缩略图只能自己解决了。于是开始是Google模式。终于功夫不负有心人,在一个国外的网站上面发现了一个折中的解决办法。

办法

其实结局的办法很简单,但是对我这个不是太懂前端的人来说还是……。

方法2016-08-08 00.29.36.png

这个方法就是在资源URL的后面(视频格式后面,有的时候视频格式后面还有其他的字符串,我是直接把.mp4后面的直接删除了,但是视频还是可以播放)加上#t=xxx,其中的xxx代表的是时间(秒)。大概的思路是这样的:就是在加载视频的时候设置视频的起始时间让视频跳转到你设置的时间上,但是时间一定要足够的小,因为大了前面的视频就看不了了。

这个方法其实还有一个用法:

用法 2016-08-08 00.50.52.png

视频会在0:06开始播放直到0:20停止播放。但是这不是自动播放,自动播放需要设置:autoplay=”autoplay”。

声明

NOTE:对于web端我是一个菜鸟,也不知道用这个方法解决这个问题是不是太蠢了,希望谁有其他更好的解决办法可以不吝赐教,谢谢。

图片上传预览

本周帮一哥们写了一个页面遇到了一些问题,特此记录一下。主要遇到的问题是图片上传预览(多个上传控件)、多个颜色选择,遇到了冲突。

来个效果一撇 2016-08-01 00.13.22.png

这是代码上传的HTML部分代码

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
26
27
28
29
30
31
32
33
34
<div id="home11" class="tab-pane in active lowerContent ">
<div class="tool floatLeft">
<span class="spanStylef floatLeft">名称</span>
<input type="text" name="appName">
</div>

<div class="upImage floatLeft">
<div class="tool floatLeft">
<span class="spanStylef floatLeft">默认图标</span>
<a href="javascript:;" class="file" onchange="javascript:setImagePreview(2);">上传图片
<input type="file" name="imagereview2" class ="inputImages">
</a>
</div>

<div class="tool floatLeft">
<span class="spanStylef floatLeft">&nbsp</span>
<img class="imagereview2" width="100" height="100" />
</div>
</div>

<div class="upImage floatLeft">
<div class="tool floatLeft">
<span class="spanStylef floatLeft">触及图标</span>
<a href="javascript:;" class="file" onchange="javascript:setImagePreview(3);">上传图片
<input type="file" name="imagereview3" class ="inputImages">
</a>
</div>

<div class="tool floatLeft">
<span class="spanStylef floatLeft">&nbsp</span>
<img class="imagereview3" width="100" height="100" />
</div>
</div>
</div>

修改上传按钮的部分css代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.file {
position: relative;
display: inline-block;
background: #D0EEFF;
border: 1px solid #99D3F5;
border-radius: 4px;
padding: 4px 12px;
overflow: hidden;
color: #1E88C7;
text-decoration: none;
text-indent: 0;
line-height: 20px;
}
.file input {
position: absolute;
font-size: 100px;
right: 0;
top: 0;
opacity: 0;
}
.file:hover {
text-decoration: none;
}

这是JS部分的代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function setImagePreview(avalue) {
//input
var docObjs = document.getElementsByClassName("inputImages");
var docObj = docObjs[avalue];
if (docObj.files && docObj.files[0]) {
var imgObjPreviews = document.getElementsByClassName(docObj.name);
var imgObjPreview = imgObjPreviews[0];
if (avalue == 0) {
imgObjPreview.style.display = 'block';
imgObjPreview.style.width = '200px';
imgObjPreview.style.height = '350px';
}else {
//火狐下,直接设img属性
imgObjPreview.style.display = 'block';
imgObjPreview.style.width = '100px';
imgObjPreview.style.height = '100px';
}
imgObjPreview.src = window.URL.createObjectURL(docObj.files[0]);
} else {
//IE下,使用滤镜
// docObj.select();
// var imgSrc = document.selection.createRange().text;
// var localImagId = document.getElementById("localImag");
// //必须设置初始大小
// localImagId.style.width = "100px";
// localImagId.style.height = "100px";
// //图片异常的捕捉,防止用户修改后缀来伪造图片
// try {
// localImagId.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
// localImagId.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc;
// } catch(e) {
// alert("您上传的图片格式不正确,请重新选择!");
// return false;
// }
// imgObjPreview.style.display = 'none';
// document.selection.empty();
}
return true;
}

问题与解决:

问题一:是上传按钮默认的文件上传是这样的

默认 2016-08-01 00.26.51.png

但是我需要的是这样的:

目标 2016-08-01 00.28.07.png

解决方案:就是将fileAPI放在你需要的控件上面,然后将fileAPI设置为透明,然后点击你需要的控件其实就是点击了fileAPI。还有一个方案就是用js:将你的控件的点击事件里面的返回为fileAPI的事件。这样点击你的控件就完成了fileAPI事件了,(我想的,没有去实现喔)

问题二:点击事件冲突

一开始我是通过id选择器来标记image与input的,后来发现多个上传按钮就需要多个js判定,会有很多的重复代码。于是后来我改为了用类选择器但是类名一样无法将image与input对应。于是我将input的name与与image的类名写成一样,通过input的name找到对应的image。

NOTE:我前端开发很久没有弄了,很多忘记了,如有错误。请亲们一定要指出啊!

iOS 下加载本地HTML/js/css/image 等路径问题

今天在项目中遇到一个问题:我将H5的文件拖入项目中,在webView上添加H5,运行时发现H5的样式与图片等都没有了。经过多种测试后发现:是路径的问题。

在ios项目下添加本地HTML/js/css/image 当拖入项目时有两种选择:

一个是 Create groups for any added folders(创建虚拟结构-包结构)

一个是 Create folder references for any added folders 创建实体结构)

如果选择前者,当APP编译过后引入的文件会被放在同一个文件夹下面会忽略你原本的文件夹。因此在HTML文件中的路径就会出现问题。如果你选择了前者那么HTML文件中引入CSS,js,图片等就不需要添加前缀路径了,直接写文件名就行。

引入文件方式:

1
2
3
4
NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString * htmlString = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] resourcePath]];
[self.webView loadHTMLString:htmlString baseURL:baseURL];

如果选择后者,当APP编译过后引入的文件会按照原本的目录结构存放,这个时候就需要添加相对路径。

引入文件方式:

1
2
3
4
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"huaiha/index.html" 

relativeToURL:[[NSBundle mainBundle] bundleURL]]]];

iOS-widget-Today 扩展

今天要分享的是通知中心扩展中的-Today扩展(ios8推出),ios目前可以使用的扩展有:today扩展(widget-即通知栏的今天一栏)、键盘自定义、文件管理、照片编辑扩展、通知扩展(推送)、分享扩展等。扩展与拥有这个扩展主应用的生命周期是独立的。他们是两个独立的进程。

一、目标:

我项目是希望在widget中添加一个H5的页面方便以后的自定义。点击对应按钮去到相应界面,我也不知道这样算不算滥用widget,因为之前看见过有人的应用被苹果拒绝就是因为滥用widget导致的。

二、实现:

1.因为widget是一个单独的进程所以需要创建一个target:

首先 2016-07-24 23.01.34.png

然后 2016-07-24 23.01.13.png

2.代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
- (void)viewDidLoad {
[super viewDidLoad];
// 调整Widget的高度
self.preferredContentSize = CGSizeMake(0, 200);

// 1、创建UIWebView:
UIWebView *mWebView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];

// 2、设置属性:
mWebView.scalesPageToFit = YES;// 自动对页面进行缩放以适应屏幕
// 检测所有数据类型 设定电话号码、网址、电子邮件和日期等文字变为链接文字

[mWebView setDataDetectorTypes:UIDataDetectorTypeAll];
mWebView.delegate = self;

// 打开URL
NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
[mWebView loadRequest:request];
[self.view addSubview:mWebView];

[self makeButtonWithTitle:@"返回" frame:CGRectMake(0, 0, 80, 64) button:_backBtn];
[self makeButtonWithTitle:@"前进" frame:CGRectMake(self.view.frame.size.width - 80, 0, 80, 64) button:_forWardBtn];
[self makeButtonWithTitle:@"刷新" frame:CGRectMake(100, 0, 80, 64) button:_refreshBtn];

}

// 取消widget默认的inset,让应用靠左
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {
return UIEdgeInsetsZero;
}

- (void)makeButtonWithTitle:(NSString *)title frame:(CGRect)frame button:(UIButton *)btn {
btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:title forState:UIControlStateNormal];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(skip:) forControlEvents:UIControlEventTouchUpInside];
[btn setFrame:frame];

if ([title isEqualToString:@"返回"]) {
btn.tag = 101;
} else if([title isEqualToString:@"前进"]) {
btn.tag = 102;
}else {
btn.tag = 103;
}
[self.view addSubview:btn];
}

- (void)skip:(UIButton *)button
{
if (button.tag == 101) {
[self.extensionContext openURL:[NSURL URLWithString:@"iOSWidgetApp://action=GotoHomePage"] completionHandler:^(BOOL success) {
NSLog(@"101 open url result:%d",success);
}];
}
else if(button.tag == 102) {
[self.extensionContext openURL:[NSURL URLWithString:@"iOSWidgetApp://action=GotoOtherPage"] completionHandler:^(BOOL success) {
NSLog(@"102 open url result:%d",success);
}];
}else {
[self.extensionContext openURL:[NSURL URLWithString:@"iOSWidgetApp://action=GotoOtherPages"] completionHandler:^(BOOL success) {
NSLog(@"102 open url result:%d",success);
}];
}
}

运行与结果展示:

运行 2016-07-24 23.02.28.png

效果图 2016-07-25 09.55.44.png

扩展与主程序的交互-数据共享

这就要涉及扩展与应用之间的数据共享了-App Groups.

首先在主应用的target > Capabilities下 打开App Groups 点击+ 在group.后面输入标识符,

Snip20160725_1.png

再去扩展的target下进行相同的操作,记得group.后的标识符要一致。

#####代码:

在上面的扩展代码里面已经定义了点击事件,这里主要是主应用接收到信息后进行判断和处理。

在这之前还需要先配置URL schems,在主程序的plist里面:

plist 2016-07-25 10.40.15.png

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
26
27
28
29
30
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

NSString* prefix = @"iOSWidgetApp://action=";

UIWebView *webView = [[UIWebView alloc]initWithFrame:[UIScreen mainScreen].bounds];
webView.backgroundColor = [UIColor clearColor];
webView.delegate = self;
[webView setUserInteractionEnabled:YES];//是否支持交互
[webView setOpaque:NO];//opaque是不透明的意思
[webView setScalesPageToFit:YES];//自动缩放以适应屏幕
webView .scrollView.bounces = NO;// 禁止UIWebView下拉拖动效果
NSString *path;
if ([[url absoluteString] rangeOfString:prefix].location != NSNotFound) {
NSString* action = [[url absoluteString] substringFromIndex:prefix.length];
if ([action isEqualToString:@"GotoHomePage"]) {
path = [[NSBundle mainBundle] pathForResource:@"help" ofType:@"html"];
}
else if([action isEqualToString:@"GotoOtherPage"]) {
path = [[NSBundle mainBundle] pathForResource:@"setting" ofType:@"html"];
}else {
path = [[NSBundle mainBundle] pathForResource:@"healthyArticle" ofType:@"html"];
}
NSURL *urll = [NSURL fileURLWithPath:path];
NSURLRequest* request = [NSURLRequest requestWithURL:urll] ;
[webView loadRequest:request];
[self.rootView.view addSubview:webView];
self.rootView.view.backgroundColor = [UIColor whiteColor];
}
return YES;
}

因为我是需要到对应的H5页面所以是添加的H5页面。

注意:

1.当程序内存不足时,苹果优先会杀死扩展,因此需要注意内存的管理。

2.在配置team是账号需要一致(我测试的时候免费账号好像还不行,需要付费的账号)

3.在iOS10上面还可以从左滑主页面和锁屏进入widget。

4.today只有在下拉的时候才会更新,通知栏两边的更新机制是不一样的。

5.一般更新路径:viewDidLoad->viewWillAppear,但是如果你下拉过于频繁就只会执行viewWillAppear里面的,因此更新代码最好放在viewWillAppear里面。

如有错误地方,万望指出,谢谢!

gitHub hexo 个人博客

一直以来就想搭建一个自己的博客,不想其它网站那么杂乱,需要一个纯粹的记录成长之路的地方。查了很多资料,最后决定用hexo 搭建一个静态网页,托管在gitHub上。下面我就介绍一下我的搭建之路,我的搭建网页

1. gitHub

gitHub 的注册及配置我就不介绍了,这个哪里都可以查到,我介绍一下注册过后远程仓库的创建。
首先创建远程仓库:
屏幕快照 2016-07-16 02.49.16.png
在后面的Respository name 里面输入:gavincarter1991.github.io 这个格式是定的(gavincarter1991 需要填写你的用户名)我没有测试过如果不填写自己用户名的后果,不过查了很多资料都推荐这样填写,有的还是不以这样的方式会报错,没有实践,我没有发言权。
屏幕快照 2016-07-16 02.49.37.png

2. homebrew安装

1
2
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

1
brew install node

查看安装是否成功:

1
2
npm -v

1
2
node -v

安装成功会显示版本号:
屏幕快照 2016-07-16 03.09.16.png

3. 开始安装hexo

首先进入你需要存放博客的文件夹,然后:

1
npm install hexo -g

查看版本号:

1
hexo version

初始化项目:(类似于git)

1
hexo init

4. 开始使用

创建页面:

1
hexo new post "My First Blog"

生成静态文件(会在当前目录下生成一个新的叫做public的文件夹)

1
hexo g # 或者hexo generate

开启本地服务 用于在本地浏览 Ctrl+C退出查看

1
hexo s # 或者hexo server,可以在输入http://localhost:4000/ 查看 或者 按住Command 双击命令行下的网址(http://localhost:4000/)

这时网页已经成型了。

接下来就是要部署到gitHub上 只需要在配置文件_config.xml中作如下修改:

1
2
3
4
deploy:
type: git
repo: git@github.com:gavincarter1991/gavincarter1991.github.io
branch: master

当然gavincarter1991位置还是填你的信息

然后安装一个自动工具,方便以后页面的部署:

1
npm install hexo-deployer-git --save

部署去gitHub:

1
hexo d

以后每一次部署的一般步骤:

1
2
3
hexo clean
hexo g
hexo d

5.写文章

首先;

1
hexo new post "My First Blog"

然后去目录:source_posts下找到My First Blog.md(markdown文件)开始编辑文章了。我Mac用的是Mou编辑器,你可以自由选择适合自己的markdown编辑器。这里有markdown使用技巧
写好以后就可以按照前面的部署常用步骤进行部署了。

6. 其他

1.主题:hexo有很多第三方主题可以选择,通过git clone
2.配置修改参数详见 我写几个常用的:
头像:把图片放在主题内 source/images/,图片链接地址可以填 /images/avatar.png 然后在当前主题的_config.yml 不是根目录的_config.yml(如果你换了主题,需要根据自己选择的主题进入里面去设置)

1
2
3
4
# Sidebar Avatar
# in theme directory(source/images): /images/avatar.jpg
# in site directory(source/uploads): /uploads/avatar.jpg
avatar: /images/avatar.jpg

个人中心配置:(根目录的_config.yml)

1
2
3
4
5
6
7
# Site
title: Gavin
subtitle: 记录成长过程中的点点滴滴
description: 我爱敏敏
author: kindyourself@163.com
language: zh-Hans
timezone:

显示标签与分类:取消对应注释

1
2
3
4
5
6
7
8
# When running the site in a subdirectory (e.g. domain.tld/blog), remove the leading slash (/archives -> archives)
menu:
home: /
categories: /categories
#about: /about
archives: /archives
tags: /tags
#commonweal: /404.html

然后创建分类

1
hexo new page "categories"

在/source/categories下有个index.md 按照如下填写:

1
2
3
4
5
6
---
title: categories
date: 2016-07-16 02:21:37
type: "categories"
comments: false
---

以后在写文章的时候加上分类就会自动创建分类了

1
2
3
4
5
6
layout: '[layout]'
title: iOS-自定义带抽屉效果的tabBar
date: 2016-07-12 23:19:35
tags: [自定义,抽屉,tabBar]
categories: "iOS" // 分类
---

创建标签

1
hexo new page "tags"

在/source/tags下有个index.md 按照如下填写:

1
2
3
4
5
6
---
title: All tags
date: 2016-07-16 02:11:12
type: "tags"
comments: false
---

以后在写文章的时候加上标签就会自动计入

1
2
3
4
5
6
layout: '[layout]'
title: iOS-自定义带抽屉效果的tabBar
date: 2016-07-12 23:19:35
tags: [自定义,抽屉,tabBar] // 标签
categories: "iOS"
---

下载主题:

1
git clone https://github.com/iissnan/hexo-theme-next themes/next

7. 总结

这个在网上还有很多很详细的教程,这是我的大致操作流程。感觉这个可以很简单,就是少去动原生的。如果你想要去捣鼓会发现还是有很多可以捣鼓的,因为他有很多的参数可以配置。我只是配置了一下我觉得在我看来重要的。有兴趣的朋友可以去捣鼓捣鼓。-太晚了,都4点了,睡觉去

iOS-自定义带抽屉效果的tabBar

demo地址:gitHub

一、先来个效果

tabBar.gif

二、代码示例

1.抽屉页作为根视图:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
@interface DrawerViewController ()
{
UITapGestureRecognizer *tapGesture;
}

//创建左边的抽屉
@property (nonatomic, strong) LeftViewController *leftViewController;

//创建右边的标签控制器
@property (nonatomic, strong) MTabBarViewController *mainViewController;
//抽屉是否显示的标示

@property (nonatomic, assign) BOOL isOpen;
@end

@implementation DrawerViewController

- (void)dealloc
{
//移除通知
[[NSNotificationCenter defaultCenter]removeObserver:self name:@"buttonTap" object:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];

[self createTabBarController];
[self createLeftVc];

self.view.backgroundColor = [UIColor grayColor];

//添加通知,监听TabBar的点击事件 隐藏左边抽屉
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(buttonTap) name:@"buttonTap" object:nil];

}
- (void)buttonTap
{
//抽屉展开时则隐藏
if (self.isOpen == YES) {
[self openOrHidden];
}

}

//创建左边抽屉
- (void)createLeftVc
{
self.leftViewController = [[LeftViewController alloc]init];

//抽屉控制器添加到父控制器中
[self addChildViewController:self.leftViewController];
self.leftViewController.view.frame = LeftViewStartFrame();
[self.view addSubview:self.leftViewController.view];
[self.leftViewController didMoveToParentViewController:self];

}

//创建右边的标签控制器
- (void)createTabBarController{
//
NSArray *classNames = @[@"ProductViewController",@"MessageViewController",@"OrderViewController"];

//保存viewControllers
NSMutableArray *viewControllers = [NSMutableArray array];
[classNames enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//先把字符串转化为类名
Class class = NSClassFromString(obj);

//创建ViewController
UIViewController *vc = [[class alloc]init];
UINavigationController *aNav = [[UINavigationController alloc]initWithRootViewController:vc];

[viewControllers addObject:aNav];

}];
//TabBarController 创建
_mainViewController = [[MTabBarViewController alloc]initWithViewControllers:viewControllers];
_mainViewController.view.backgroundColor = [UIColor brownColor];

//添加标签控制器到父控制器
[self addChildViewController:self.mainViewController];
self.mainViewController.view.frame = BOUNDS;
[self.view addSubview:self.mainViewController.view];
[self.mainViewController didMoveToParentViewController:self];
}

//标签控制器显示的vc的根控制器的view往右边移动
//tabBar -> Nav (ViewControllers[selectedIndex]) -> Nav.rootViewController.view
- (void)tabBar_Nav_RootViewController_viewMoveRight
{
//标签控制器当中 当前显示的控制器
UINavigationController *nav = self.mainViewController.viewControllers[self.mainViewController.selectedIndex];
//取出导航控制器的根控制器
UIViewController *rootVc = nav.childViewControllers[0];
rootVc.view.frame = RightContentEndFrame();
}

- (void)tabBar_Nav_RootViewController_viewMoveLeft
{
//标签控制器当中 当前显示的控制器
UINavigationController *nav = self.mainViewController.viewControllers[self.mainViewController.selectedIndex];
//取出导航控制器的根控制器
UIViewController *rootVc = nav.childViewControllers[0];
rootVc.view.frame = RigntContentStartFrame();
}

//显示左边抽屉
- (void)open
{
[UIView animateWithDuration:0.48 animations:^{
self.leftViewController.view.frame = LeftViewEndFrame();
[self tabBar_Nav_RootViewController_viewMoveRight];
} completion:nil];

//添加点击手势,点击某些区域的隐藏抽屉
tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tapGesture];
}

- (void)tap:(UITapGestureRecognizer *)gesturer
{
//获取点击的位置
CGPoint point = [gesturer locationInView:self.view];
if (CGRectContainsPoint(self.leftViewController.view.frame, point) == YES) {
return;
}

[self hidden];
self.isOpen = NO;
//移除手势
[self.view removeGestureRecognizer:tapGesture];
}

//隐藏左边抽屉
- (void)hidden
{
[UIView animateWithDuration:0.48 animations:^{
self.leftViewController.view.frame = LeftViewStartFrame();
[self tabBar_Nav_RootViewController_viewMoveLeft];
} completion:nil];

}

- (void)openOrHidden
{
//当前如果是隐藏,则显示
if (self.isOpen == NO) {
[self open];
}

//当前如果是显示的,则隐藏
if (self.isOpen == YES) {
[self hidden];
}

//改变隐藏标记
self.isOpen = !self.isOpen;
}
@end

2.标签视图 修改方法 - (void)selectBtn:(UIButton *)sender中的切换效果可以实现不同的切换动画与效果。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@implementation MTabBar
- (instancetype)initWithTitles:(NSArray *)titles imageNames:(NSArray *)imageNames
{
self = [super initWithFrame:TabBarFrame()];
if (self) {

//标题数组不为空,图片名字个数 = 标题个数
self.buttonBack = [[UIView alloc]initWithFrame:CGRM(0, 0, BUTTON_W, 64)];
self.buttonBack.backgroundColor = BUTTON_BACK_COLOR;
[self addSubview:self.buttonBack];

self.backgroundColor = TABBAR_BACK_COLOR;

if ([titles count] && [titles count] == [imageNames count]) {
[titles enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIButton *button = [[UIButton alloc]initWithFrame:CGRM(BUTTON_W*idx, 0, BUTTON_W, 64)];
button.tag = 1000 + idx;
[self addSubview:button];
//默认选中第一个
if (idx == 0) {
button.selected = YES;
self.selectedButton = button;
}

[button addSubview:MakeLabel(CGRM(0, 30, BUTTON_W, 34), obj)];
// // 图片宽 高分别为 44 24
CGFloat x = (BUTTON_W - 44)/2;
[button addSubview:MakeImageView(CGRM(x, 5, 44, 24),[imageNames objectAtIndex:idx])];
//添加点击方法
[button addTarget:self action:@selector(selectBtn:) forControlEvents:UIControlEventTouchUpInside];
}];
}
}
return self;
}

//button 点击方法
- (void)selectBtn:(UIButton *)sender
{
//让抽屉隐藏,发出通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"buttonTap" object:nil];

//选中的button 已经是选中状态 不用处理
if (self.selectedButton == sender) {
return;
}
//改变之前选中button的状态 为非选中状态
self.selectedButton.selected = NO;

//改变当前选中button的状态
sender.selected = YES;
self.selectedButton = sender;
//通知标签控制器显示当前button对应的viewController
if (self.callBack) {
self.callBack(sender.tag - 1000);
}
[UIView animateWithDuration:0.5 animations:^{
self.buttonBack.center = CGPointMake(BUTTON_W/2+(sender.tag - 1000) * BUTTON_W, 32);
} completion:nil];
}

UILabel *MakeLabel(CGRect frame, NSString *title)
{
UILabel *label = [[UILabel alloc]initWithFrame:frame];
// label.userInteractionEnabled = YES;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = title;
return label;
}

//根据 frame和 imageName 创建UIImageView
UIImageView *MakeImageView(CGRect frame, NSString *imageName)
{
UIImageView *imageV = [[UIImageView alloc]initWithFrame:frame];
// imageV.userInteractionEnabled = YES;
imageV.backgroundColor = [UIColor clearColor];
imageV.image = [UIImage imageNamed:imageName];
return imageV;
}
@end

3.标签控制器

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@interface MTabBarViewController ()

@end

@implementation MTabBarViewController

- (instancetype)initWithViewControllers:(NSArray *)viewControllers
{
self = [super init];
if (self) {

_viewControllers = viewControllers;
//遍历数组,添加子控制器
[_viewControllers enumerateObjectsUsingBlock:^(UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self addChild:obj];
}];
/*
@[@"商品.png",@"消息.png",@"订单.png"]
@[@"商品浏览",@"我的消息",@"我的订单"]
*/
_tabBar = [[MTabBar alloc]initWithTitles:@[@"商品浏览",@"我的消息",@"我的订单"] imageNames:@[@"商品.png",@"消息.png",@"订单.png"]];
[self.view addSubview:self.tabBar];
__weak typeof(self) weakSelf = self;
self.tabBar.callBack = ^(NSInteger index){
weakSelf.selectedIndex = index;
};
//默认选中第0个
self.selectedIndex = 0;
}
return self;
}

- (void)setSelectedIndex:(NSInteger)selectedIndex
{
//取出当前控制器 oldVc
UIViewController *oldVc = self.viewControllers[self.selectedIndex];
//取出将要显示的 控制器 newVc
UIViewController *newVc = self.viewControllers[selectedIndex];
//动画 向左边移动
newVc.view.frame = CGRectMake(S_W, 0, S_W, S_H);
//改变 newVc 的视图层次

//把newVc.view 的视图放在 self.tabBar 的下面
[self.view insertSubview:newVc.view belowSubview:self.tabBar];
[UIView animateWithDuration:0.5 animations:^{
oldVc.view.frame = CGRectMake(-S_W, 0, S_W, S_H);
newVc.view.frame = BOUNDS;
}];
_selectedIndex = selectedIndex;
}

//添加子控制器具体步骤
- (void)addChild:(UIViewController *)viewController
{
[self addChildViewController:viewController];
viewController.view.frame = BOUNDS;
//将viewContoller.view 放在最底层
[self.view insertSubview:viewController.view atIndex:0];
[viewController didMoveToParentViewController:self];

// self.view.subviews 数组 下标越小,视图层次越在下面,下标越大,视图层次越在上面
}
@end

4.视图位置控制 修改对应的视图的frame可以实现不同的视图效果

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
26
27
28
29
30
31
32
33
34
35
CGRect TabBarFrame()
{
return CGRectMake(0, S_H-64, S_W, 64);
}

//左边抽屉隐藏(开始)的位置
CGRect LeftViewStartFrame()
{
return CGRectMake(-S_W*0.75, 67,S_W*0.75 , S_H-64-64-6);
}

//左边抽屉显示(结束)的位置
CGRect LeftViewEndFrame()
{
return CGRectMake(0, 67, S_W*0.75, S_H-64-64-6);
}

//右边内容开始(抽屉隐藏时)的位置
CGRect RigntContentStartFrame()
{
return CGRectMake(0, 0, S_W, S_H);
}

//右边内容结束(抽屉显示时)的位置
CGRect RightContentEndFrame()
{
return CGRectMake(S_W*0.75, 0, S_W, S_H);
}

CGRect CGRM(CGFloat x, CGFloat y,CGFloat w,CGFloat h)
{
return CGRectMake(x, y, w, h);
}
@end

欢迎下载

与web前端朋友闲聊的发现-代码相通性

缘起

今天与一个做web前端的哥们闲聊了一会,他今天遇到了一个问题:就是在做一个混合开发的APP时候,他们H5端有一个页面需要做搜索,就是在搜索框内输入能够实时的展示搜索结果。

想法与问题

他想监听了搜索框并且实时的进行数据的请求。后来发现输入的过程一直在进行远程数据的请求,他觉得这样消耗太大了。于是想做一个延时的操作,就是等用户稍微停止输入的时候才去远程请求数据。可是没有理清这个逻辑,于是他的方法相当的复杂,好像是要将每一实时输入的数据存入数组,然后进行对比,当延时完成进行对比决定请求的数据。

插曲

但是他在这个过程中发现了一个问题,就是延时操作并没有减少网络请求的次数。这个问题在前段时间的项目中我也遇到了,就是延时操作并不是重复了,就不执行了,延时操作只是延缓操作时间,每一次的延时都会被执行。所以想要减少执行次就必须在延时操作未执行 前取消延时操作。取消的延时操作如果还没有执行,就不会执行了而不是取消后就立即执行。

讨论

这时候我想起几天前在简书上看见一个哥们写了一篇关于如何防止button被重复点击的文章,他一共介绍了三种方法,他的第二种方法:

1
2
3
4
5
6
7
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]
- (void)click:(UIButton *)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(btnClicke) object:nil];
[self performSelector:@selector(btnClicke) withObject:nil afterDelay:1];
}

就是用的延时操作他的是在button的方法里面先取消延时方法,再添加延时方法,这个对于防止button重复点击来说并不是好的方法,因为这样会影响用户的体验,每次点击button不能及时的进行响应。但是对于我朋友的这个问题却是一个很好的选择。他原本就想减缓请求次数。

结论

我发现编程语言是相通的,虽然各有各的语法,但是实现思路是一样的,特此记录。

Base64-不重要数据的简单加密

导语

最近公司要求对服务器的token等参数进行一个简单的加密,防止恶意请求。要求加密过程自定义,于是就想到了用base64,其实这不是一个加密解密的算法,其实它就是使用64个字符来对任意数据进行编码解码的,具体底层实现原理就不讨论了,它是随着iOS7推出的。

##我的实现过程(可以根据公司需求自定义):

  1. 先编码一次
  2. 对编码结果的数据交换首位字符在编码一次
  3. 对编码结果逆序在编码一次

##示例代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
+(NSString *)base64EncodedString:(NSString *)string {
Base64Encoding *base64 = [[Base64Encoding alloc] init];

// 1次
NSString *encrypt1 = [base64 base64EncodedString:string];
// 交换字符串首位次序
NSString *string1 = [base64 changeStringFirsrAndLast:encrypt1];

// 2次
NSString *encrypt2 = [base64 base64EncodedString:string1];
// 交换字符串首位次序
NSString *string2 = [base64 changeStringOrder:encrypt2];

// 3次
NSString *encrypt3 = [base64 base64EncodedString:string2];

return encrypt3;
}
// 添加逗号
- (NSString *)addSeparaedSingle:(NSString *)string {
NSMutableString *mutableString = [string mutableCopy];
NSInteger cont = mutableString.length;
for (int i = 0; i < cont - 1; i ++) {
[mutableString insertString:@"," atIndex:2 * i + 1];
}
return mutableString;
}

// 去掉逗号
- (NSString *)removeSeparaedSingle:(NSString *)string {
return [string stringByReplacingOccurrencesOfString:@"," withString:@""];
}

// 字符串转数组
- (NSMutableArray *)stringChangeArray:(NSString *)string {
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:[string componentsSeparatedByString:@","]];
return mutableArray;
}

// 数组转字符串
- (NSString *)arrayChangeString:(NSArray *)array {
return [array componentsJoinedByString:@","];
}

// 字符串交换首尾
- (NSString *)changeStringFirsrAndLast:(NSString *)string {
NSString *str = [self addSeparaedSingle:string];
NSMutableArray *mutableArray = [self stringChangeArray:str];
NSString *temp = mutableArray[0];
mutableArray[0] = mutableArray[mutableArray.count - 1];
mutableArray[mutableArray.count - 1] = temp;
NSString *arrayString = [self arrayChangeString:mutableArray];
return [self removeSeparaedSingle:arrayString];
}

// 字符串逆序
- (NSString *)changeStringOrder:(NSString *)string {
NSString *str = [self addSeparaedSingle:string];
NSMutableArray *mutableArray = [self stringChangeArray:str];
NSArray *reversedArray = [[mutableArray reverseObjectEnumerator] allObjects];
NSString *arrayString = [self arrayChangeString:reversedArray];
return [self removeSeparaedSingle:arrayString];
}

// 编码
- (NSString *)base64EncodedString:(NSString *)string {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
return [data base64EncodedStringWithOptions:0];
}

###结束语:

这个可以根据公司的要求跟后台写的好加密的规则,解密就交给后台了,方法:initWithBase64EncodedData 采用逆向规则解密即可,当然这个是极其容易被破解的,涉及敏感数据是不可使用这个方法的。

  • Copyrights © 2015-2025 kindyourself@163.com
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信