计算总行数\总页数
总数 : 2476
每页显示的最大数量 : 35
总页数 : (2476 + 35 - 1) / 35
pagesCount = (总数 + 每页显示的最大数量 - 1) / 每页显示的最大数量
总数 : 1660
每一行显示的最大数量 : 30
总行数 : (1660 + 30 - 1) / 30
rowsCount = (总数 + 每行显示的最大数量 - 1) / 每行显示的最大数量
查找字符串的常见方法
// 如果range.location == 0, 说明是以searchString开头
// 如果range.location == NSNotFound或者range.length == 0, 说明没找到对应的字符串
- (NSRange)rangeOfString:(NSString *)searchString;
// 是否以str开头
- (BOOL)hasPrefix:(NSString *)str;
// 是否以str结尾
- (BOOL)hasSuffix:(NSString *)str;
// 是否包含了str(不管头部\中间\尾部)
- (BOOL)containsString:(NSString *)str;
reloadData
tableView的更新方法,底层原理原来位置在哪,更新后自动定位到哪,不会改变位置,以后更新tableView的时候,不要用MJ_header beginRefresh,用tableView的reloadData方法,可以增加界面的流程性
NSUserDefault保存报错
我原来认为NSUserDefaults存不了数组,又换成了字典,但是还是报错,最后求助网友大神解决了,是我里边的数据结构有"<null>",而NSUserDefaults是不能被成功解析并存入的,所有在存入之前需要将里边的"<null>"改成""即可。
用代码修改图片颜色
- 1.首先需要是Xcode的assets里面的图片.
- 2.在属性面板里可以看到Render As,选择Template Image.
- 3.在使用图片的视图中利用tintColor控制图片颜色(比如UIImageView,UIButton).
UITabBarController的设置
UITabBarController系统默认的选中颜色是蓝色,设置tintColor属性,改变选中标签的颜色
使用自定义图片来设置tabBar,使用initWithTitle:image:tag:方法,苹果官方文档说明图片的大小为30*30,Retina屏为60*60(stackoverflow上有大神指出,UITabBarItem图标的最佳尺寸是48*32)
关于UIBezierpath
UIBezierPath 有个原生的方法- (void)appendPath:(UIBezierPath *)bezierPath, 这个方法作用是俩个路径有叠加的部分则会镂空.
设置UITabBar的tabBarItem的文字和图片
//设置图片居中,这里的4.5,根据实际中间按钮图片大小来决定
Vc.tabBarItem.imageInsets = UIEdgeInsetsMake(4.5, 0, -4.5, 0);
//设置不显示文字,将title的位置设置成无限远,就看不到了
Vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
设置图片拉伸
[self.msgBackGoundImageView setHighlightedImage:[[UIImage imageNamed:@"bg_chat_me"] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 20, 8, 20) resizingMode:UIImageResizingModeStretch]];
oc源码中经常出现的值
1 << 5
2的5次方
给动画设置key
1. [self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];
//动画开始时- (void)animationDidStart:(CAAnimation *)anim{
if ([anim isEqual:[self.imageView.layer animationForKey:@"Animation"]]) {
NSLog(@"动画组执行了");
}
}
2.[transformAnima setValue:@"TransformAnima" forKey:@"AnimationKey"];
if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]) {
NSLog(@"位置移动动画执行结束");
} else if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"TransformAnima"]){
NSLog(@"旋转动画执行结束");
}}
``
##边缘拖动
```objc
//UIScreenEdgePanGestureRecognizer跟pan(平移)手势差不多,需要从边缘进行拖动,在控制器转换的时候是有用的
runtime关联对象
objc_setAssociatedObject(self, &key, object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
关联对象中的对象相当于字典中的value,key相当于字典中的key。根据key可以取到你关联的对象
presentationLayer
CALayer *layer = subView.layer.presentationLayer; //图片的显示层
每个图层属性的显示值都被存储在一个叫做呈现图层的独立图层当中,他可以通过-presentationLayer方法来访问。这个呈现图层实际上是模型图层的复制,但是它的属性值代表了在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值
#-如果你在实现一个基于定时器的动画,而不仅仅是基于事务的动画,这个时候准确地知道在某一时刻图层显示在什么位置就会对正确摆放图层很有用了。
#-如果你想让你做动画的图层响应用户输入,你可以使用-hitTest:来判断指定图层是否被触摸,这时候对呈现图层而不是模型图层调用-hitTest:会显得更有意义,因为呈现图层代表了用户当前看到的图层位置,而不是当前动画结束之后的位置。
//手机截屏
在iOS7 以前, 获取一个UIView的快照有以下步骤: 首先创建一个UIGraphics的图像上下文,然后将视图的layer渲染到该上下文中,从而取得一个图像,最后关闭图像上下文,并将图像显示在UIImageView中。现在我们只需要一行代码就可以完成上述步骤了:
[view snapshotViewAfterScreenUpdates:NO];
//设置背景为某张图片
UIImage *launchImage = [UIImage imageNamed:@"图片名称"];
self.backgroundColor = [UIColor colorWithPatternImage:launchImage];
//contents是layer的一个属性
transitionLayer.contents = (id)_imageView.layer.contents;
iOS根据陀螺仪等传感器获得夹角等数据
__weak typeof(self) weakSelf = self;
if ([self.motionManager isDeviceMotionAvailable]) {
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion * _Nullable motion,
NSError * _Nullable error) {
//获取这个然后使用这个角度进行view旋转,可以实现view保持水平的效果,设置一个图片可以测试
double rotation = atan2(motion.gravity.x, motion.gravity.y) - M_PI;
weakSelf.arImageView.transform = CGAffineTransformMakeRotation(rotation);
//2. Gravity 获取手机的重力值在各个方向上的分量,根据这个就可以获得手机的空间位置,倾斜角度等
double gravityX = motion.gravity.x;
double gravityY = motion.gravity.y;
double gravityZ = motion.gravity.z;
//获取手机的倾斜角度(zTheta是手机与水平面的夹角, xyTheta是手机绕自身旋转的角度):
double zTheta = atan2(gravityZ,sqrtf(gravityX*gravityX+gravityY*gravityY))/M_PI*180.0;
double xyTheta = atan2(gravityX,gravityY)/M_PI*180.0;
}];
}
忽略某种类型的警告
BuildSeting -> Other Warning Flags -> -Wno-documentation
VR全息实景技术的实现
捕捉宠物小精灵
- 左右方向靠的是地图定位利用didUpdateHeading
// 已经更新到用户设备朝向时调用 左右定位
- 上下方向靠的是陀螺仪z轴偏移角度CMMotionManager
到处走
- 左右方向靠的是地图定位,location Lat,Lng 计算夹角
tabBar只有图片没有文字
//设置图片居中,这里的4.5,根据实际中间按钮图片大小来决定
Vc.tabBarItem.imageInsets = UIEdgeInsetsMake(4.5, 0, -4.5, 0);
//设置不显示文字,将title的位置设置成无限远,就看不到了
Vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
SDImageCache是怎么做数据管理的?
SDImageCache分两个部分,一个是内存层面的,一个是硬盘层面的。
内存层面的相当是个缓存器,以Key-Value的形式存储图片。当内存不够的时候会清除所有缓存图片。
用搜索文件系统的方式做管理,文件替换方式是以时间为单位,剔除时间大于一周的图片文件。
当SDWebImageManager向SDImageCache要资源时,先搜索内存层面的数据,如果有直接返回,没有的话去访问磁盘,将图片从磁盘读取出来,然后做Decoder,将图片对象放到内存层面做备份,再返回调用层。
数组倒序
[array reverseObjectEnumerator]
显式动画和隐式动画
1、隐式动画通过隐式事务实现动画 。( 除显式事务外,任何对于CALayer属性的修改,都是隐式事务.这样的事务会在run-loop中被提交. )
//此方法传入NO启动隐式动画
[CATransaction setDisableActions:NO];
2、显式动画有多种实现方式,显式事务是一种实现显式动画的方式。 ( 通过明确的调用begin,commit来提交动画 )
//开始动画
[CATransaction begin];
//显式事务默认开启动画效果,kCFBooleanTrue关闭
[CATransaction setValue:(id)kCFBooleanFalse forKey:kCATransactionDisableActions];
//动画执行时间
[CATransaction setValue:[NSNumber numberWithFloat:5.0f] forKey:kCATransactionAnimationDuration];
//开始提交执行动画
[CATransaction commit];
在UITableView滚动到最底端的时候自动加载数据
当scrollview scroll的时候,可以根据判断条件判断此时的tableview已经滑到了最底端,以下是判断条件 那个scrollview就是tableview
scrollView.contentOffset.y + (scrollView.frame.size.height) > scrollView.contentSize.height
就表示已经到底部了 可以进行在判断条件内执行更多了
LaunchScreen.storyboard设置启动页黑屏
将启动图放在根目录下就好了
系统定位方案
如果能够接受GPS信息,那么优先采用GPS定位,否则采用WiFi或者蜂窝基站定位,在WiFi和蜂窝基站之间优先使用WiFi,如果无法使用WiFi才使用蜂窝基站定位
隐藏导航条底部的黑线
[self.navigationController.navigationBar setShadowImage:[UIImage imageWithColor:[UIColor clearColor]]];
CAShapeLayer
* CAShapeLayer的动画都是对属性strokeEnd的操作
CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
basic.duration = 1.0;
basic.fromValue = @(0.1f);
basic.toValue = @(1.0f);
[_shapeLayer addAnimation:basic forKey:@"basic"];
关于输入框随键盘弹出而上移
* tableView或者scrollView的滚动而取消编辑的行为,全部放到
- scrollViewWillBeginDragging方法中,因为,键盘弹出后,再设置scrollView的滚动 -> contentOffset,不调用此方法,而调用scrollViewDidScroll方法
textView或者label,设置点击位置高亮原理
//设置了textView的selectedRange为NSRange类型,selectedTextRange,为UITextRange类型,textView的范围判断是这样判断的
// 给定指定的range, 返回range对应的字符串的rect
// 返回数组的原因是因为文字可能换行
self.tv.selectedRange = spec.range;
NSArray *rects = [self.tv selectionRectsForRange:self.tv.selectedTextRange];
self.tv.selectedRange = NSMakeRange(0, 0);
for (UITextSelectionRect *selectionRect in rects) {
CGRect rect = selectionRect.rect;
if (rect.size.width == 0 || rect.size.height == 0) continue;
if (CGRectContainsPoint(rect, point)) {
return YES;
}
else
{
return NO;
}
}
TextKit
// MARK: -懒加载
/*
只要textStorage中的内容发生变化, 就可以通知layoutManager重新布局
layoutManager重新布局需要知道绘制到什么地方, 所以layoutManager就会文textContainer绘制的区域
*/
// 这里先讲解三种类的关系:
//1、NSTextStorage保存并管理UITextView显示的文字信息,并且可以灵活的修改文字属性
//2、NSLayoutManager用于管理NSTextStorage中文字内容的排版布局
//3、NSTextContainer定义一个矩形区域用于存放已经进行了排版并设置好属性的文字
fileprivate func setupSystem()
{
// 1.将layoutManager添加到textStorage
textStorage.addLayoutManager(layoutManager)
// 2.将textContainer添加到layoutManager
layoutManager.addTextContainer(textContainer)
}
override func layoutSubviews() {
super.layoutSubviews()
// 3.指定区域
textContainer.size = bounds.size
}
mutablePointer ->指针
缩放的本质是修改transform,而修改transform不会影响到view的bounds只有frame会受到影响
任何输入控件都有两个属性(inputView 键盘,inputAccessoryView 工具条)
collectionView中cell之间有空隙原因
1、
minimumInteritemSpacing 和 minimumLineSpacing 都带“ minimum ”前缀,说明是最小间距,但是并不保证 item 之间的间距一定是最小,取决于 autolayout 布局时, spacing = (屏幕 width -(itemWidth * itemNum) - contentInset.left - contentInset.right)/(itemNum - 1),spacing 的值是否为 0.5 的倍数
2、
似乎 cell.width 必须是整数,如果为小数的话就会有空隙
UIView弹簧动画和关键帧动画
1、弹性动画
[UIView animateWithDuration:1. delay:0. usingSpringWithDamping:.4 initialSpringVelocity:5. options:(UIViewAnimationOptionCurveEaseIn) animations:^{
} completion:^(BOOL finished) {
}];
2、关键帧动画
[UIView addKeyframeWithRelativeStartTime:0. relativeDuration:.25 animations:^{
}];
[UIView animateKeyframesWithDuration:1.5 delay:0 options:(UIViewKeyframeAnimationOptionAllowUserInteraction) animations:^{
} completion:^(BOOL finished) {
}];
两种transform动画的变化
CGAffineTransformConcat就是把两种变化效果联系起来,有个动态的过渡过程
约束设置(技巧)
1、类似textview,collectionView,tableView,scrollView,这种类型的控件,设置约束时,不要自己去计算高度,要使用他们的contentSize属性去完成高度的计算,方便快捷(取巧)。
2、cell中有图片排布的cell高度计算,不要在tableView的代理方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
来进行高度计算,麻烦而且显得技术差。
我们应该在cell中使用 Masonry 代码更新图片或者其他控件的高度,动态更新,最后调用cell的【self layoutifNeed】方法,刷新cell高度
/// collectionView的高度用这个,不要用contentSize.height
self.LayoutH.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height + 20;
自定义转场动画时注意细节
- 1、present/dismiss 遵守<UIViewControllerTransitioningDelegate>协议, 转场实现四个方法,分别需要-> 转场时动画对象和手势对象。
self.transitioningDelegate = self;
self.modalPresentationStyle = UIModalPresentationCustom;
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
return [XWPresentOneTransition transitionWithTransitionType:XWPresentOneTransitionTypePresent];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
return [XWPresentOneTransition transitionWithTransitionType:XWPresentOneTransitionTypeDismiss];
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator{
return _interactiveDismiss.interation ? _interactiveDismiss : nil;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)animator{
XWInteractiveTransition *interactivePresent = [_delegate interactiveTransitionForPresent];
return interactivePresent.interation ? interactivePresent : nil;
}
2、而push/pop遵守<UINavigationControllerDelegate>代理方法,根据UINavigationControllerOperation类型不同进行判断。
self.navigationController.delegate = pushVC;
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
_operation = operation;
//分pop和push两种情况分别返回动画过渡代理相应不同的动画操作
return [XWPageCoverTransition transitionWithType:operation == UINavigationControllerOperationPush ? XWPageCoverTransitionTypePush : XWPageCoverTransitionTypePop];
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{
if (_operation == UINavigationControllerOperationPush) {
XWInteractiveTransition *interactiveTransitionPush = [_delegate interactiveTransitionForPush];
return interactiveTransitionPush.interation ? interactiveTransitionPush : nil;
}else{
return _interactiveTransitionPop.interation ? _interactiveTransitionPop : nil;
}
}
类似自定义转场效果(没有手势而已)
//制造出和自定义转场动画相似的效果
UIImageView *imgV =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, SXSCREEN_W, SXSCREEN_H)];
imgV.image = [self getImage];
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:imgV];
[self.navigationController popViewControllerAnimated:NO];
imgV.alpha = 1.0;
[UIView animateWithDuration:0.3 animations:^{
imgV.frame = CGRectMake(0, SXSCREEN_H/2, SXSCREEN_W, 0);
imgV.alpha = 0.0;
} completion:^(BOOL finished) {
[imgV removeFromSuperview];
}];
iOS富文本和html字符串互转
//html字符串转换为富文本
NSString *htmlStr = @"我的<span style='color:red'>aafaf微</span>我的<span style='color:red'>aafaf微</span>";
NSAttributedString *att = [[NSAttributedString alloc] initWithData:[htmlStr dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];
//富文本转换为html(最后相当于整个网页代码,会有css等)
NSDictionary *dic = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute:@(NSUnicodeStringEncoding)};
NSData *data = [att dataFromRange:NSMakeRange(0, att.length) documentAttributes:dic error:nil];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUnicodeStringEncoding];
NSCache缓存(还是YYCahce比较好用)
* 1 NSCache和NSMutableDictionary的相同点与区别:
相同点:
NSCache和NSMutableDictionary功能用法基本是相同的。
区别:
NSCache是线程安全的,NSMutableDictionary线程不安全
NSCache线程是安全的,Mutable开发的类一般都是线程不安全的
当内存不足时NSCache会自动释放内存(所以从缓存中取数据的时候总要判断是否为空)
NSCache可以指定缓存的限额,当缓存超出限额自动释放内存
缓存限额:
1) 缓存数量
@property NSUInteger countLimit;
2) 缓存成本
@property NSUInteger totalCostLimit;
苹果给NSCache封装了更多的方法和属性,比NSMutableDictionary的功能要强大很多
网易新闻图文混排实现猜想
1、根据网易接口返回的数据,自己编写处理HTML代码,进行图文混排,这样处理的好处在于可以自己编写js或者css代码,修改属性,进行图片缓存处理,保证图片不会多次加载,方便管理。
webView加载图片缓存问题,解决方法有两种
1、在webView中加入js脚本,加载时拿到图片地址,用SDWbeImage下载下来后,再调用脚本展示图片。
2、通过NSURLProtocol,在加载时判断有无图片,有的话生成一个NSURLResponse对象,将图片放进去,没有的话,就去请求数据。
百度地图中的问题。
1、解决了百度地图起点与自己位置重叠时,自己位置将起点位置遮挡问题。在自定义大头针代码中加上这句,效果类似滴滴。
self.layer.zPosition = -1;
2、自定义annotation 和annotationView 以保证数据储存和展示
3、百度地图中
1.UIView和核心动画区别?
核心动画只能添加到CALayer
核心动画一切都是假象,并不会改变真实的值。
app内购解决方案
内购,简单说明一下,如果你购买的商品,是在本app中使用和消耗的,就一定要用内购,否则会被拒绝上线,例如:游戏币,在线书籍,app中使用的道具等。如果购买的就是普通的商品,例如淘宝买东西等,就不需要用内购,想怎么玩都自己说了算。
1、如果一定要用支付宝的话就审核的时候用内购,上线以后后台改配置用支付宝,不过这样抓到的话会死的比较惨,就算采用这种方法还是要有购物的,要不然还是会被拒,说集成了支付宝没用
2、外跳浏览器支付 不会被拒,对于外跳的 苹果审核一般很少管
支付宝支付完成后的验签(同步异步)
验签是支付宝与后台服务器的工作,手机端不用管。
1、同步即项目中使用的获取到结果后调用后台接口,我们可以拿到验签的结果。但是订单的状态是由后台更改的,后台说成功就是成功。
2、异步即支付宝调用支付时订单order中的一个参数,notify_url,调用一个url,传给后台一些参数,进行验证,验证结构我们拿不到,但是,我们只需要显示支付成功,订单的状态从后台获取就可以了。
iOS开发支付宝支付成功以后的回调问题
如果手机中安装了支付宝,会走AppDelegate中的方法,但是我里面的log始终不打印,是不是和回调的notifyURL有关系呢
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
/*这里面不走*/
}];
return YES;
}
上面的这个方法走过之后,调用支付宝时的回调方法也会走,这个是问什么呢
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@",resultDic);
}];
当客户端调用支付宝软件的时候,进入到支付宝,然后用home键进入后台,把自己的客户端给杀死,,此时在进入支付宝继续支付,支付完成后,会进入appdelegate中调用openURL的方法,再次打开客户端,block里面的结果此时就可以拿到了。
- http://www.cocoachina.com/bbs/read.php?tid-322784-page-1.html
支付宝支付和微信支付的区别和相同点
相同点:支付宝和微信支付完成后都会对商户服务器有一个异步通知即notify_url。个人观点:就算有异步通知,也应该请求服务器对订单是否支付成功进行验证。
不同点:1、支付宝没有订单查询接口,而微信可以对订单是否支付成功进行查询。
2、支付宝支付成功之后的验证操作方式只能是通知,而微信可以使用代理,通过代理进行验证之后的操作。
双击定点图片放大
UITapGestureRecognizer *)doubleTap
CGPoint point = [doubleTap locationInView:doubleTap.view];
CGFloat touchX = point.x;
CGFloat touchY = point.y;
touchX *= 1/self.scrollview.zoomScale;
touchY *= 1/self.scrollview.zoomScale;
touchX += self.scrollview.contentOffset.x;
touchY += self.scrollview.contentOffset.y;
CGRect zoomRect = [self zoomRectForScale:self.scrollview.maximumZoomScale withCenter:CGPointMake(touchX, touchY)];
[self.scrollview zoomToRect:zoomRect animated:YES];
- (CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center
{
CGFloat height = self.frame.size.height / scale;
CGFloat width = self.frame.size.width / scale;
CGFloat x = center.x - width * 0.5;
CGFloat y = center.y - height * 0.5;
return CGRectMake(x, y, width, height);
}
NavicationControll中设置控件y值问题
Navbar的translucent属性影响高度设置,还有设置图片背景图片,相当于设置translucent属性为NO,从而影响设置y值问题。
1、设置的图片有值时,y值会改变,//iOS7及以后的版本支持,self.view.frame.origin.y会下移64像素至navigationBar下方。在控制器中设置self.edgesForExtendedLayout = UIRectEdgeNone时,y值会回到0。
2、设置的图片没有时,即[UIImage new],这个时候y值还是0的状态(这种情况需要注意,框架改变透明度也是利用runtime增加了属性,对背景图片设置[UIImage new]做到的)
//设置背景图片会导致y值下移64,但是[UIImage new]不会改变y值
类似QQ空间效果实现原理
不能设置为tableViewHeader,因为,header的话也会随着tableView的下拉而移动,要实现的话需要[tableView addSubview imageView],tableivew 设置内边距为图片高度,的方法来实现。
tableHeaderView与viewForHeaderInSection是不同的,不要混淆
tableHeaderView的高度并不是heightFroRowInSection获取的,tableview -> headerView和footerView是自己设置的,不是代理方法获取的,不是同一个东西
打开QQ指定聊天窗口
NSString *string = [NSString stringWithFormat:@"mqq://im/chat?chat_type=crm&uin=136279559&version=1&src_type=web"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:string]];
app登录页面与主界面的切换
根据QQ界面显示情况,登录界面与主界面切换(登录,退出),代码实现为
self.view.window.rootViewController = rootVC;
而我之前的实现都是显示登录界面后再跳转到别的界面,这样体验效果不好,之后的实现方式都换成这种。
视频播放器
1、MPMoviePlayerController(可以自定义大小,工能足够强大,封装的很好,很难自定义样式)
2、MPMoviePlayerViewController(全屏播放)
3、AVPlayer(播放状态,进度,需要自己设置观察者,需要借助AVPlayerLayer对象, 根据player创建图层, 添加到视图上否则只有声音没有图像)
AVPlayer监听的4中状态分别为
- 1 status 预播放状态,有三种情况
- 2 loadedTimeRanges 缓冲进度
- 3 playbackBufferEmpty seekToTime后,缓冲数据为空,而且有效时间内数据无法补充,播放失败
- 4 playbackLikelyToKeepUp seekToTime后,可以正常播放,相当于readyToPlay,一般拖动滑竿菊花转,到了这个这个状态菊花隐藏
本地通知与远程推送
##本地通知
* 在iOS中如果点击一个弹出通知(或者锁屏界面滑动查看通知),默认会自动打开当前应用。
由于通知由系统调度那么此时进入应用有两种情况:
如果应用程序已经完全退出那么此时会调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法;<br>
如果此时应用程序还在运行(无论是在前台还是在后台)则会调用
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification方法接收消息参数。
##远程推送
此函数无论是程序被杀死还是处于后台,只要用户点击了通知,都会被调用,因此如果是iOS7,则不必在didFinishLaunchingWithOptions中做处理,只在下面函数做处理即可,此时应避免在didFinishLaunchingWithOptions函数中也做重复处理。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// userInfo
}
ios 10 之后苹果有
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
iOS10系统的更新,苹果给了我们2个代理方法来处理通知的接收和点击事件,这两个方法在<UNUserNotificationCenterDelegate>的协议中,
- http://www.jianshu.com/p/bcece05517fc
- http://www.jianshu.com/p/ad43bc1a970a
- http://www.jianshu.com/p/f5337e8f336d
webView后退是否刷新
- UIWebView很弱,而且前进后退的时候还会reload
- WKWebView倒是不错,性能各方面都和Safari差不多,也没有这些reload的问题。不过WK的网络请求不能通过NSURLProtocol拦截,经过同事“很不细致的调研”发现WK的网络请求是跨进程
网友评论