你的激情被狗吃了吗

编程如逆水行舟,不进则退


  • 首页

  • 标签

  • 归档

  • 搜索

iOS实现后台推送语音播报+推送后台唤醒后台蓝牙打印

发表于 2018-04-18 |

最近入职的公司是做聚合支付的,主要面对的用户都是商家,所以当顾客扫码付款的时候,即使商家的APP在后台也要进行收款金额的播报和小票的蓝牙打印(我进来的时候APP都存在两年了都没这俩功能,表示很逗逼),所以研究了一下后台推送的语音播报功能和推送后台唤醒后台蓝牙打印,在这里做个笔记。

阅读全文 »

UIView以自身的某一点为圆心进行旋转

发表于 2018-03-12 |

最近面试的时候被问到了如何以某个View上的某一个点为圆心进行动画旋转,因为一般处理View的旋转的动画的时候都是基于transform.rotation.z为圆心进行旋转的,查了资料总结出了实现任意点为圆心的旋转方式,内容如下。

阅读全文 »

JavaScriptCore使用

发表于 2017-12-27 |

JavaScriptCore

JavaScriptCore是webkit的一个重要组成部分,主要是对JS进行解析和提供执行环境。代码是开源的,可以下下来看看(源码)。iOS7后苹果在iPhone平台推出,极大的方便了我们对js的操作。我们可以脱离webview直接运行我们的js。iOS7以前我们对JS的操作只有webview里面一个函数 stringByEvaluatingJavaScriptFromString,JS对OC的回调都是基于URL的拦截进行的操作。大家用得比较多的是WebViewJavascriptBridge和EasyJSWebView这两个开源库,很多混合都采用的这种方式。

阅读全文 »

WebViewJavascriptBridge使用和原理剖析

发表于 2017-12-26 |

WebViewJavascriptBridge的github地址

WebViewJavascriptBridge的基本原理

在WebViewJavascriptBridge.m的文件重写了UIWebView的shouldStartLoadWithRequest:navigationType方法,此方法在html页面的js动作触发时、url变化的时、网页内容变化的时会自动调用。

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
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
//判断这个UIWebView是否注册了WebViewJavascriptBridge
if (webView != _webView) { return YES; }
//获取请求的URL
NSURL *url = [request URL];
__strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
//通过检查scheme和host,就可以清楚的知道,这个请求是不是WebViewJavascriptBridge的重定向请求。
if ([_base isWebViewJavascriptBridgeURL:url]) {
//判断URL是否是需要bridge的URL
if ([_base isBridgeLoadedURL:url]) {
//通过injectJavascriptFile方法注入JS
[_base injectJavascriptFile];
} else if ([_base isQueueMessageURL:url]) {
//判断URL是否是队列消息,若是,则执行查询命令JS并刷新消息队列
NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
[_base flushMessageQueue:messageQueueString];
} else {
//URL被识别为未知的消息。
[_base logUnkownMessage:url];
}
return NO;
} else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
} else {
return YES;
}
}
阅读全文 »

CoreAnimation笔记

发表于 2017-12-19 |

总结一下Core Animation的使用,本文主要借鉴了这篇博客
博客地址

1.简介

iOS动画主要是指Core Animation框架。
官方使用文档地址为Core Animation Guide。
Core Animation是iOS和macOS平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑,不会加重CPU的负担而影响程序的运行速度。

阅读全文 »

NSDictionary实现原理

发表于 2017-12-08 |

NSDictionary(字典)是使用 哈希表来实现key和value之间的映射和存储的, hash函数设计的好坏影响着数据的查找访问效率。数据在hash表中分布的越均匀,其访问效率越高。而在Objective-C中,通常都是利用NSString 来作为键值,其内部使用的hash函数也是通过使用 NSString对象作为键值来保证数据的各个节点在hash表中均匀分布。
见NSDictionary中最常用的一个方法原型:

1
- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;

NSDictionary中的key是唯一的,key可以是遵循NSCopying 协议和重载- (NSUInteger)hash;、- (BOOL)isEqual:(id)object;方法的任何对象。也就是说在NSDictionary内部,会对 aKey 对象 copy 一份新的。而 anObject 对象在其内部是作为强引用(retain或strong)。

hash 方法是用来计算该对象的 hash 值,最终的 hash 值决定了该对象在 hash 表中存储的位置。所以同样,如果想重写该方法,我们尽量设计一个能让数据分布均匀的 hash 函数。
isEqual : 方法是为了通过 hash 值来找到 对象 在hash表中的位置。

在调用setObject: forKey: 后,内部会去调用 key 对象的 hash 方法确定 object 在hash表内的入口位置,然后会调用 isEqual : 来确定该值是否已经存在于 NSDictionary中。

补充一个小知识:iOS setValue和setObject的区别:

1
2
- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;
- (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;

首先:setObject: ForKey:是NSMutableDictionary特有的;setValue: ForKey:是KVC的主要方法。

区别:

(1) setValue: ForKey:的value是可以为nil的(但是当value为nil的时候,会自动调用removeObject:forKey方法);

setObject: ForKey:的value则不可以为nil。

(2) setValue: ForKey:的key必须是不为nil的字符串类型;

setObject: ForKey:的key可以是不为nil的所有继承NSCopying的类型。

KVO使用和底层实现原理

发表于 2017-12-06 |

使用

KVO 能帮助我们让视图和模型保持同步。控制器可以观察视图依赖的属性变化。

阅读全文 »

GCD语法笔记

发表于 2017-11-30 |
  • 并行+异步:就是真正的并发,新开有有多个线程处理任务,任务并发执行(不按顺序执行)
  • 串行+异步:新开一个线程,任务一个接一个执行,上一个任务处理完毕,下一个任务才可以被执行
  • 并行+同步:不新开线程,任务一个接一个执行
  • 串行+同步:不新开线程,任务一个接一个执行
阅读全文 »

面试问题总结

发表于 2017-11-28 |

基础类

1 ARC下的assign和weak区别

weak 比 assign 多了一个功能就是当属性所指向的对象消失的时(也就是内存引用计数为0)会自动赋值为 nil ,这样再向 weak 修饰的属性发送消息就不会导致野指针操作crash。

结论:在 ARC 模式下编程时,指针变量一定要用 weak 修饰,只有基本数据类型和结构体需要用 assgin ,例如 delegate ,一定要用 weak 修饰。

阅读全文 »

模拟tvOS中的3D浮动效果

发表于 2017-11-27 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-(void)setUpSomething{

self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(0, 10);
self.layer.shadowRadius = 10.0f;
self.layer.shadowOpacity = 0.3f;

cardImageView = [[UIImageView alloc]initWithFrame:self.bounds];
cardImageView.image = [UIImage imageNamed:@"Group 24"];
cardImageView.layer.cornerRadius = 5.0f;
cardImageView.clipsToBounds = YES;
[self addSubview:cardImageView];

UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panInCard:)];

[self addGestureRecognizer:panGes];

cardParallaxView = [[UIImageView alloc]initWithFrame:cardImageView.frame];
cardParallaxView.image = [UIImage imageNamed:@"Group 25"];
cardParallaxView.layer.transform = CATransform3DTranslate(cardParallaxView.layer.transform, 0, 0, 200);
[self insertSubview:cardParallaxView aboveSubview:cardImageView];

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-(void)panInCard:(UIPanGestureRecognizer *)panGes{

CGPoint touchPoint = [panGes locationInView:self];

if (panGes.state == UIGestureRecognizerStateChanged) {

CGFloat xFactor = MIN(1, MAX(-1,(touchPoint.x - (self.bounds.size.width/2)) / (self.bounds.size.width/2)));
CGFloat yFactor = MIN(1, MAX(-1,(touchPoint.y - (self.bounds.size.height/2)) / (self.bounds.size.height/2)));

cardImageView.layer.transform = [self transformWithM34:1.0/-500 xf:xFactor yf:yFactor];
cardParallaxView.layer.transform = [self transformWithM34:1.0/-250 xf:xFactor yf:yFactor];


}else if (panGes.state == UIGestureRecognizerStateEnded){

[UIView animateWithDuration:0.3 animations:^{
cardImageView.layer.transform = CATransform3DIdentity;
cardParallaxView.layer.transform = CATransform3DIdentity;
} completion:NULL];

}

}
1
2
3
4
5
6
7
8
9
-(CATransform3D )transformWithM34:(CGFloat)m34 xf:(CGFloat)xf yf:(CGFloat)yf{

CATransform3D t = CATransform3DIdentity;
t.m34 = m34;
t = CATransform3DRotate(t, M_PI/9 * xf, 0, 1, 0);
t = CATransform3DRotate(t, M_PI/9 * yf, -1, 0, 0);
return t;

}
12
LiuXin

LiuXin

编程如逆水行舟,不进则退

18 日志
20 标签
© 2018 LiuXin
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.3