商城类网站建设+数据库,如何做美食网站设计,WordPress自定义json接口,小程序登录入口网页版官网iOS 需要在info.plist中 添加的权限 1 概述 UIKit 框架提供了 iOS 或 Apple tvOS App 所需的基础架构。它提供了用于实施界面的窗口和视图架构#xff0c;用于向 App 提供多点触控和其他类型输入的事件处理基础架构#xff0c;以及管理用户、系统和 App 之间互动所需的主运行… iOS 需要在info.plist中 添加的权限 1 概述 UIKit 框架提供了 iOS 或 Apple tvOS App 所需的基础架构。它提供了用于实施界面的窗口和视图架构用于向 App 提供多点触控和其他类型输入的事件处理基础架构以及管理用户、系统和 App 之间互动所需的主运行循环。该框架提供的其他功能包括动画支持、文档支持、绘图和打印支持、当前设备的相关信息、文本管理和显示、搜索支持、辅助功能支持、App 扩展支持和资源管理。 // 框架的入口import UIKit/UIKit.h UIKit是Cocoa Touch的一部分提供了一组类来创建和管理iOS App的窗口和视图、处理事件、绘图和动画等框架中的类具有如下继承关系结构 常用的UIKit组件有
·UIView及子类包括UIScrollViewUITableView、UICollectionView、UITextView、UILabel、UIControlUIButton、UITextField、UIPickerView等
·与控件相关但不能被人所直观看到的图形、绘图、打印、文本等的配置与控制包括UIViewController、UIImage等。
1.1 界面构建
·xib轻量级的可通过拖拽进行界面创作和布局本质是个XML文件。
·nibNeXT Interface Builderxib编译后得到的二进制文件。
·storyboard重量级的自iOS 5引入用来描述整个软件的多个界面也是个XML文件。
storyboard使用方式
·通过拖放对象来完成静态的界面布局通过连线把静态的元素与代码进行关联如IBOutlet和IBAction。
storyboard优缺点
·它可以用于描述不同视图之间的关联具有原型表项prototype cell和静态表项static cell特性和简化自动布局等特点
·性能较差容易发生冲突不便于进行模块化管理。
1.2 生命周期 UIApplication对象是应用程序的象征一个 UIApplication 对象就代表一个应用程序。一个 iOS 程序启动后创建的第一个对象就是 UIApplication 对象。利用 UIApplication 对象能进行一些应用级别的操作。每个iOS APP都只有一个UIApplication或者很少有的UIApplication子类实例。当应用程序启动时系统会调用UIApplicationMain(_:_:_:_:)函数。每一个应用都有自己的单例的UIApplication 对象如果试图在程序中新建一个UIApplication对象那么将报错。 The Main Run Loop主运行循环负责处理用户相关的事件。UIApplication对象在程序启动时启动Main Run Loop它处理事件和更新视图的界面它是运行在程序的主线程上的这样保证了接收到用户相关操作的事件是按顺序处理的。UIApplication对象处理传入用户事件的初始路由它将UIControl类对象转发给它的动作消息分派给适当的目标对象。UIApplication对象维护一个打开的窗口UIWindow对象列表它可以用来检索任何应用程序的UIView对象。 UIApplication对象会被赋予一个代理对象以处理应用程序的生命周期事件比如程序启动和关闭。在移动操作系统中应用程序很容易受到来电、锁屏等干扰这时UIApplication对象也会通知它的代理对象让代理对象来处理这些系统事件。 UIApplication状态1Not running未运行程序没启动2Inactive未激活程序在前台运行没有接收到事件3Active激活程序在前台运行而且接收到了事件4Background后台 程序在后台而且能执行代码执行完毕或超时后会进入挂起状态 (Suspended)有的程序经过特殊的请求后可以长期处于 Background 状态5Suspended挂起程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时程序还是停留在内存中的当系统内存低时系统就把挂起的程序清除掉为前台程序提供更多的内存。 UIApplication详细介绍 Apple Developer Documentation iOS应用程序生命周期(前后台切换,应用的各种状态)详解_空杯子_的博客-CSDN博客 懒加载的优势
懒加载延迟加载把对象的实例化尽量延迟即启动应用程序时不加载这个资源只有在运行时用到才加载按需加载。
例如如果启动APP后一次性加载大量数据、图片和音视频等资源就有可能会耗尽移动设备内存。这时就可以使用懒加载技术。具体来说重写属性的getter方法先判断该属性是否为nil如果为空再进行实例化否则直接返回属性。
懒加载的好处有不必将创建对象的代码全部写在viewDidLoad方法中代码的可读性更强每个控件分别负责各自的实例化处理代码的耦合程度低不必在初始化阶段加载所有数据节省内存也就是系统的内存占用率会减少减少服务器端压力。
1.2.1 UIApplication
·UIApplicationMain int main(int argc, char * argv[]) {NSString * appDelegateClassName;appDelegateClassName NSStringFromClass([AppDelegate class]);/*** 前两个参数和C语言一致* 第三个参数是NSString *principalClassName如果是nil那么它的值将从Info.plist获取如果Info.plist没有则默认为 UIApplication。principalClass这个类除了管理整个程序的生命周期之外什么都不做它只负责监听事件然后交给delegateClass处理。* 第四个参数是NSString *delegateClassName作用是对一系列系统事件如程序将要启动、程序启动完成、程序进入后台、程序进入前台、程序退出等做出反应。AppDelegate是UIApplication默认的代理已经遵守了UIApplicationDelegate协议。**/return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}·APP的生命周期 ·didFinishLaunchingWithOptions
在这个函数中可以用如下类似的代码创建一个UIWindow // 伪代码self.window [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds] 如果在指定模版时选择了storyboard那么Info.plist的Main storyboard file nameUIMainStoryboardFile会指向主storyboard。UIApplicationMain实例化代理后会向代理询问其window属性的值如果该值为 nil则创建UIWindow对象并将其指定给代理的window属性然后将主storyboard的初始视图控制器实例化并分配给窗口的rootViewController属性结果是将其作为根视图控制器放置在窗口中再向窗口发送makeKeyAndVisible消息。
1.2.2 视图控制器
每个视图控制器VC都维护一个视图层次视图层次的根结点是根视图可以通过self.view来访问每个视图都有自己的子视图。 调用时机 方法 作用 默认实现 UIStoryboard获取视图控制器或者NSBundle加载nib文件时 - (instancetype)initWithCoder:(NSCoder *)coder 从nib文件、xib或storyboard中加载视图控制器 在当前所有控件元素都加载好之后 awakeFromNib 该消息发送给所有拥有已加载元素的对象表明对其他加载对象的所有引用都是有效且可用的。 VC在view属性被请求且当前view为nil时 loadView VC在初始化时创建一个UIView对象作为默认视图可以通过self.view来访问。 从Storyboard或xib中加载VC的视图设为当前VC的视图属性如果没有关联的文件则创建一个空白视图给VC的视图属性。 视图层次已经放入内存中。在控制器因为某种原因如要显示需要使用到该视图的时候调用。一个VC生命周期内只会调用一次。 -(void)viewDidLoad 可以在此完成自定义数据和控件当几何内容被确定之后viewWillLayoutSubview和viewDidLayoutSubviews被调用 视图的基本的初始化除了几何图形的初始化 当收到视图在窗口将可见时。可能会调用多次。 -(void)viewWillAppear:(BOOL)animated: 对不可见时可能改变的数据进行同步 不执行任何操作 当收到视图在窗口已可见时此时视图已在屏幕上渲染完成 -(void)viewDidAppear:(BOOL)animated: 不执行任何操作 视图被驳回时。当收到视图将去除、被覆盖或隐藏于窗口的通知时。 -(void)viewWillDisappear:(BOOL)animated: 不执行任何操作 视图被驳回后。当收到视图已去除、被覆盖或隐藏于窗口的通知时。 -(void)viewDidDisappear:(BOOL)animated 不执行任何操作 返回是否支持不同方向的旋转视图 shouldAutorotateToInterfaceOrientation 支持或禁止自动旋转 支持 进行旋转视图前 willAnimateRotationToInterfaceOrientation 用于调整旋转视图
2 MVC
·在iOS中多数数据源视图控件View都有一个dataSource属性数据源通过与控制器Controller交互间接地从我们定义的数据模型Model中获取数据视图和控制器之间可以相互访问模型既不能访问视图也不能访问控制器这种模式是MVC·视图是用户在屏幕上看到的模型提供数据控制器是它们的中介。 3 UIView
UIView是UIResponder的子类是许多常用控件的父类如UIScrollView、UILabel、UIControl和UIPickerView等。屏幕上所有的UI元素都是控件控件指的就是UIView类或者子类。
·Apple将所有控件的基本属性都封装到UIView中如frame、bounds、center、backgroundColor、hidden、alpha、opaque和userInteractionEnabled等
·每个controller都对应一个默认的UIView对象该控件的大小是整个屏幕每个UIView对象都是容器都被该控件所容纳。在一个控制器.m文件中self.view就是调用控制器的默认UIView。
UIView有三个结构体CGPointCGRectCGSize。CGPoint确定了view的起始坐标
CGSize确定view的长宽CGRect确定了整个视图位置和大小。 /* 关于UIView隐藏属性、alpha属性和不透明属性之间有什么区别? */
[_uiview setHidden:YES];
[_uiview setAlpha:0.0f];
/* 差异很微妙。根据UIView文档:
opaque 告诉系统视图没有透明度因此渲染速度更快因为可以跳过混合计算
hidden 是布尔属性仅更改当前视图的可见性并将其从 ui 事件中隐藏
alpha 是一个动画属性。
设置alpha0.0f或hiddenYES具有相同的视觉效果。然而当您有大量嵌套视图时使用hidden 不仅在图形意义上而且从UI事件中实际隐藏视图可能会导致更有效的响应者链. */ 3.1 Frame和Bounds
frame和bounds都是UIView的属性。
·bounds通常用来描述视图的大小bounds大小改变时当前视图的中心点不会发生改变当前视图的大小发生改变。bounds改变位置时改变的是子视图的位置自身没有影响实质上改变了当前视图的坐标系原点 ·frame用来描述视图的位置origin和大小size当前视图的位置是以父视图坐标系来确定。frame大小改变时当前视图的坐标系原点不会改变当前视图的大小发生改变。使用frame的布局是唯一确定的不会随父视图变化而变化除非在某个时间点再次设置了frame。
3.2 CALayer
CALayer是屏幕上的一个具有可见内容的矩形区域每个UIView都有一个根CALayer其所有的绘制视觉效果都是在这个layer上进行的。
通过UIView的layer属性可以访问这个层。
3.3 UITextView
UITextView是UIScrollView的子类具有UIScrollView的属性和方法包括frame、bounds和backgroundColor等。 UITextView *textmtview [[UITextView alloc] initWithFrame:CGRectMake(80, 365, 250, 50)]; // Initialize 富文本字符串AttributedString可以分为NSAttributedString和NSMutableAttributedString通过将AttributedString赋值给UILabel、UITextField或UITextView的attributedText属性来添加文字样式。
NSTextAttachment该类使用文本附件对象作为附件属性的值存储在键下的富文本字符串中。 NSTextAttachment* attch [[NSTextAttachment alloc] init];
CGFloat diameter [self fontLineHeight:[UIFont systemFontOfSize:14]];
attch.image [UIImage imageNamed:waybill_detail_help];
attch.bounds CGRectMake(0, -5, diameter, diameter);
NSAttributedString* attStr [NSAttributedString attributedStringWithAttachment:attch];
[attMutStr appendAttributedString:attStr]; 3.4 UITableView
3.4.1 数据源和代理
·视图对象表视图只管理表中数据的表示而不管理数据本身。
·数据源UITableView的数据源用于提供数据行数以及每一行显示的数据等数据源通常是遵守UITableViewDataSource协议的对象。
UITableViewDataSource协议 表视图数据源协议该协议声明了管理表视图数据和cell的方法。数据源对象响应表中与数据相关的请求。它还可以直接管理表的数据或者与app的其他部分协调一起来管理该数据。 protocol UITableViewDataSourceNSObject
required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // 设置表视图每个分组的行数
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; // 控制每一行返回的内容
optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // 设置分区数
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // 设置分区头的内容
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; // 控制Cell是否可以编辑
// Other...
end ·代理设置UITableView的代理对象来响应事件比如选中某一行代理通常是遵守UITableViewDelegate协议的对象。使用表视图通常需要遵守UITableViewDataSource和UITableViewDelegate这两个协议。
UITableViewDelegate协议 用于管理选择、配置节页眉和页脚、删除和重新排序单元格以及在表格视图中执行其他操作的方法。使用此协议的方法来管理以下功能创建和管理自定义页眉和页脚视图指定行、页眉和页脚的自定义高度提供高度估计以获得更好的滚动支持缩进行内容响应行选择等。 // Cell被点击后需要做什么
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// 告诉UITableView每一个Cell的高度是多少
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 3.4.2 cell重用
·UITableView有一个重用池机制来管理UITableViewCell当列表滑动时一部分cell会移出窗口UITableView默认只加载在屏幕上显示的cell窗口外的cell会被放入一个对象池里等待复用。当UITableView要求dataSource返回UITableViewCell时dataSource会先尝试从对象池获取一个如果池中有未使用的UITableViewCelldataSource会用新的数据配置这个UITableViewCell然后返回给UITableView重新显示到窗口中从而避免创建新对象。
·UITableViewCell有个NSString *reuseIdentifier属性可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier。当UITableView要求dataSource返回UITableViewCell时先通过一个字符串标识到对象池中尝试获取对应类型的UITableViewCell对象如果没有对应类型的对象就用这个标识来初始化一个UITableViewCell对象。
重用方法定义cell的标识、从对象池里取cell、判断取出cell是否为空为空就初始化cell。 - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {static NSString *showUserInfoCellIdentifier ShowUserInfoCell;UITableViewCell *cell [tableView dequeueReusableCellWithIdentifier:showUserInfoCellIdentifier];if (cell nil) {cell [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:showUserInfoCellIdentifier];}return cell;
} 3.5 UILabel
UILabel 是基础的文本组件。 // 自适应计算UILabel高度(CGFloat)calculateLabelHeightWithString:(NSString *)string font:(UIFont *)font labelWidth:(CGFloat)labelWidth {NSMutableParagraphStyle *paragraphStyle [[NSMutableParagraphStyle alloc]init];paragraphStyle.lineBreakMode NSLineBreakByWordWrapping;CGFloat height [string boundingRectWithSize:CGSizeMake(labelWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:{NSFontAttributeName:font,NSParagraphStyleAttributeName:paragraphStyle.copy} context:nil].size.height;short scale [UIScreen mainScreen].scale;height scale * height;height ceilf(height);return height / scale;
} 4 UIViewController
UIViewController是视图控制器它由控制器view组成。它能够完成以下功能 控制视图的代码逻辑并拥有自己的视图 控制器与控制器之间的通信 视图与Model之间的传值 添加子控制器 展示界面信息 添加子控件
4.1 UITabBarController
UITabBarController就是多个ViewController的容器他们之间的层级是平行的它会在底部添加一个TabBar的UIView通过点击TabBar上的按钮tabBarItem来切换对应的ViewController。
4.2 UINavigationController
UITabBarController一般配合UINavigationController来使用这样可以实现多Tab多栈跳转页面视图。
4.3 Segue 类型 作用 Show (Push) 此segue调用showViewController: sender:方法显示新内容。对于大多数视图控制器show segue 在源视图控制器上以modal方式呈现新内容。但UISplitViewController和UINavigationController类会重写showViewController: sender:方法以根据自身设计处理呈现方式。如在UINavigationController中视图控制器会被push到其导航堆栈。 Show Detail (Replace) 此segue调用showDetailViewController: sender:方法显示新内容。Show Detail segue仅与嵌入在UISplitViewController对象内的视图控制器相关此时分割视图用新内容替换detail controller。在其他视图控制器中show detail会以modal形式呈现新内容。 Present Modally 调用方法presentViewController: animated: completion:使用指定presentation style和transition style以modal形式呈现新内容 Present As Popover 在horizontally regular environment视图控制器显示在弹出窗口中在horizontally compact environment视图控制器使用全屏模式显示。
5 UIScreen // 带有状态栏的 Rect
CGRect bound [UIScreen mainScreen].bounds;
// 不带有状态栏的 Rect
CGRect frame [UIScreen mainScreen].applicationFrame;
// 设备的自然分辨率
float scale [UIScreen mainScreen].scale; PPIPixel Per Inch by diagonal表示沿着对角线每英寸所拥有的像素Pixel数目。PPI数值越高代表显示屏能够以越高的密度显示图像即通常所说的分辨率越高、颗粒感越弱。在同样的逻辑坐标系下320×4801 point scale*pixel在iPhone4~6中缩放因子scale2在iPhone6中缩放因子scale3。可以理解为scale绝对长度比point/pixel单位长度内的数量比pixel/point。 1 MAMapkit 高德地图 iOS SDK 是一套基于 iOS 8.0 及以上版本的地图应用程序开发接口供开发者在自己的iOS应用中加入地图相关的功能包括地图显示含室内、室外地图、与地图交互、在地图上绘制、兴趣点搜索、地理编码、离线地图等功能。 高德地图 iOS SDK 专业版是在 iOS SDK 已有服务的基础上新增支持了自定义地图在线加载、自定义地图元素纹理等功能便于开发者完成基于自身场景的更深层、更个性化地图的开发需求。 ·注册
使用高德地图首先需要注册获取应用KEY申请流程见官网。
·导入第三方库
自动配置使用Cocoapods
1编辑Podfile platform :ios, 15.0 #手机的系统
target demogmap dopod AMap2DMap #2D地图SDK(2D和3D不能同时使用)pod AMapSearch #搜索功能
end 2安装依赖库M1 sudo arch -x86_64 gem install ffi
arch -x86_64 pod install 手动配置
1添加依赖库 2添加资源文件
需要引入的资源文件包括AMap.bundle其中AMap.bundle 在 MAMapKit.framework 包中AMap.bundle资源文件中存储了定位、默认大头针标注视图等图片可利用这些资源图片进行开发。
申请好key值后需要在application里配置用户的key值
3修改Info.plist增加如下键值 keyNSAppTransportSecurity/keydictkeyNSAllowsArbitraryLoads/keytrue//dictkeyNSLocationAlwaysAndWhenInUseUsageDescription/keystring始终允许访问位置信息/stringkeyNSLocationWhenInUseUsageDescription/keystring使用应用期间允许访问位置信息/string 4在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中添加申请的key - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// Override point for customization after application launch.[[AMapServices sharedServices] setEnableHTTPS:YES];[AMapServices sharedServices].apiKey 4ca2e61dc9bd7504896f99b4558a2e7b;return YES;
} 1.1 定位 - (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view._mapView [[MAMapView alloc] initWithFrame:self.view.bounds];_mapView.autoresizingMask UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;[_mapView setShowsUserLocation:YES]; // 显示定位[_mapView setUserTrackingMode:MAUserTrackingModeFollow];[self.view addSubview:_mapView];[_mapView setDelegate:self]; // 设置委托
} 1.2 手势 - (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.UILongPressGestureRecognizer *lpress [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector(longPress:)];lpress.delegate self;[_mapView addGestureRecognizer:lpress];
}- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {return YES;
}- (void)longPress:(UIGestureRecognizer*)gestureRecognizer{if (gestureRecognizer.state UIGestureRecognizerStateEnded){return;}[_mapView removeAnnotation:_pointAnnotation];CGPoint touchPoint [gestureRecognizer locationInView:_mapView]; //获取坐标点CLLocationCoordinate2D touchMapCoordinate [_mapView convertPoint:touchPoint toCoordinateFromView:_mapView];_pointAnnotation.coordinate touchMapCoordinate;_pointAnnotation.title 选定位置;[_mapView addAnnotation:_pointAnnotation];[self.mapView addOverlay:[MACircle circleWithCenterCoordinate:touchMapCoordinate radius:1000]];[self setLocationWithLatitude:touchMapCoordinate.latitude AndLongitude:touchMapCoordinate.longitude];
} 1.3 标注 - (MAAnnotationView*)mapView:(MAMapView *)mapView viewForAnnotation:(id MAAnnotation)annotation {if ([annotation isKindOfClass:[MAPointAnnotation class]]){static NSString *pointReuseIndetifier pointReuseIndetifier;MAPinAnnotationView *annotationView (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier];if (annotationView nil){annotationView [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier];}annotationView.canShowCallout YES;annotationView.animatesDrop YES;annotationView.draggable YES;annotationView.rightCalloutAccessoryView [UIButton buttonWithType:UIButtonTypeDetailDisclosure];annotationView.pinColor [self.annotations indexOfObject:annotation] % 3;return annotationView;}return nil;
} 1.4 描绘蒙层 - (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(idMAOverlay)overlay {if([overlay isKindOfClass:[MACircle class]]){MACircleRenderer *render [[MACircleRenderer alloc] initWithCircle:overlay];render.fillColor [UIColor colorWithRed:1.0 green:0.8 blue:0.0 alpha:0.8]; //圆圈的填充颜色render.strokeColor UIColor.blueColor; //圆圈的轮廓颜色render.lineWidth 3.f; //圆圈轮廓的粗细return render;}return nil;
} 1.5 发起路径规划搜索 - (IBAction)findWayAction:(id)sender {// 设置步行路径规划请求参数AMapWalkingRouteSearchRequest* walkRequest [[AMapWalkingRouteSearchRequest alloc] init];// 设置起点walkRequest.origin [AMapGeoPoint locationWithLatitude:((MAPointAnnotation*)(_annotations[0])).coordinate.latitude longitude:((MAPointAnnotation*)(_annotations[0])).coordinate.longitude];// 点击设置终点walkRequest.destination [AMapGeoPoint locationWithLatitude:((MAPointAnnotation*)(_pointAnnotation)).coordinate.latitude longitude:((MAPointAnnotation*)(_pointAnnotation)).coordinate.longitude];// 发起路径搜索发起后会执行代理方法[_search AMapWalkingRouteSearch:walkRequest];
}//路线解析
- (MAPolyline *)polylinesForPath:(AMapPath *)path{if (path nil || path.steps.count 0){return nil;}NSMutableString *polylineMutableString [ mutableCopy];for (AMapStep *step in path.steps) {[polylineMutableString appendFormat:%;,step.polyline];}NSUInteger count 0;CLLocationCoordinate2D *coordinates [self coordinatesForString:polylineMutableString coordinateCount:count parseToken:;];MAPolyline *polyline [MAPolyline polylineWithCoordinates:coordinates count:count];free(coordinates), coordinates NULL;return polyline;
}//解析经纬度
- (CLLocationCoordinate2D *)coordinatesForString:(NSString *)stringcoordinateCount:(NSUInteger *)coordinateCountparseToken:(NSString *)token{if (string nil){return NULL;}if (token nil){token ,;}NSString *str ;if (![token isEqualToString:,]){str [string stringByReplacingOccurrencesOfString:token withString:,];}else{str [NSString stringWithString:string];}NSArray *components [str componentsSeparatedByString:,];NSUInteger count [components count] / 2;if (coordinateCount ! NULL){*coordinateCount count;}CLLocationCoordinate2D *coordinates (CLLocationCoordinate2D*)malloc(count * sizeof(CLLocationCoordinate2D));for (int i 0; i count; i){coordinates[i].longitude [[components objectAtIndex:2 * i] doubleValue];coordinates[i].latitude [[components objectAtIndex:2 * i 1] doubleValue];}return coordinates;
} 2 相机和相册
iOS开发中通常获取照片的方式有三种1.直接调用摄像头拍照 2.从相册中选择 3.从图库中选择。 通常使用到的类或框架有UIImagePickerController、AssetsLibraryiOS 4 - iOS 9、PhotoKitiOS8等。
2.1 UIImagePickerController
UIImagePickerController 是系统提供的用来获取图片和视频的接口。用 UIImagePickerController 类来获取图片视频大体分为以下几个步骤 初始化 UIImagePickerController 类 设置 UIImagePickerController 实例的数据来源类型 设置代理 如果需要做图片修改的话设置 allowsEditing YES。 // 需遵守协议 UIImagePickerControllerDelegate, UINavigationControllerDelegate
_uiipc [[UIImagePickerController alloc] init];
//获取照片的类型
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {_uiipc.sourceType UIImagePickerControllerSourceTypePhotoLibrary;
}
//设置代理
_uiipc.delegate self;
//是否允许编辑
_uiipc.allowsEditing YES;#pragma mark UIImagePickerControllerDelegate- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker {[picker dismissViewControllerAnimated:YES completion:nil];
}- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {UIImageView* imgview _uiiv;// 获取选择的图片UIImage* org [info objectForKey:UIImagePickerControllerOriginalImage];// 修改图片UIImage* cir [self CircleImageWithRef:org AndDiameter:100.0f AndBorderWidth:2.0f AndBorderColor:[UIColor redColor]];// 替换原来的头像[picker dismissViewControllerAnimated:YES completion:^(void) {[UIView animateWithDuration:0.5f animations:^(void) {[self.view setAlpha:1.0f];[imgview setImage:cir];} completion:nil];UIAlertController* uiac [UIAlertController alertControllerWithTitle:提示 message:更改头像 preferredStyle:UIAlertControllerStyleAlert];[uiac addAction:[UIAlertAction actionWithTitle:好的 style:UIAlertActionStyleDefault handler:nil]];[self presentViewController:uiac animated:YES completion:nil];}];
} 2.2 AssetsLibrary
AssetsLibrary框架包含ALAssetsLibrary、ALAssetsGroup、ALAsset、ALAssetsFilter、ALAssetRepresentation五个类提供从相册中读取相片、将相片保存到相册获取相册信息增加相册等功能。
·ALAssetsLibrary类用来构建资源库对象这个对象用来整体操作系统的相册资源可以实现查看相册列表增加相册保存图片到相册等功能例如enumerateGroupsWithTypes方法列举所有相册
·ALAssetsGroup相册类通过valueForProperty方法查看不同属性的值如ALAssetsGroupPropertyName相册名。ALAssetsGroup类有几个方法posterImage方法是相册的封面图片numberOfAssets方法获取该相册的图片视频数量通过enumerateAssetsUsingBlock方法列举出所有照片使用setAssetsFilter:(ALAssetsFilter *)filter过滤照片或者视频等
·ALAsset类也可以通过valueForProperty方法查看不同属性的值如ALAssetPropertyTypeasset的类型有三种ALAssetTypePhoto, ALAssetTypeVideo or ALAssetTypeUnknown。另外还可以通过该方法获取ALAssetPropertyLocation照片位置ALAssetPropertyDuration视频时间ALAssetPropertyDate照片拍摄日期等
·ALAssetRepresentation类是ALAsset类的defaultRepresentation方法的返回值类型该类的作用就是获取该资源图片的详细资源信息。
2.3 PhotoKit
在 iOS 和 macOS 中PhotoKit是App在使用、管理图片和视频的框架,而且还包括了iCloud上面的图片以及实时照片。PhotoKit 提供了支持为照片应用程序构建照片编辑扩展的类。在 iOS、macOS 和 tvOS 中PhotoKit 还提供对照片应用程序管理的照片和视频资产的直接访问。
3 QuartzCore
QuartzCore包含CoreAnimation框架是iOS系统的基本渲染框架是一个OC语言框架是一套基于CoreGraphics的OC语言封装封装出了基本渲染类CALayer。QuartzCore框架用于提供iOS开发中的视觉反馈开发的界面都是QuartzCore框架中CALayer图层合成的结果CALayer提供了接口用于给自己添加Animation。
3.1 CALayer 在iOS中UIView控件并不是直接显示在屏幕上而是在创建UIView视图对象的时候内部会自动创建一个图层即CALayer对象而UIView把要显示的东西绘制在层上待到需要显示时硬件将所有的层拷贝然后按Z轴的高低合成最终的显示结果。CALayer本质上是一块包含一幅位图的缓冲区由视图创建的层为隐式层而手动创建的层称为显式层。CALayer实现了CAMediaTiming协议CALayer通过CAMediaTiming协议实现了一个有层级关系的时间系统。除了CALayerCAAnimation也采纳了此协议用来实现动画的时间系统。
树状结构
Layer也和View一样存在着一个层级树状结构称之为图层树Layer Tree直接创建的或者通过UIView获得的用于显示的图层树称之为模型树Model Tree模型树中的对象是应用程序与之交互的对象。此树中的对象是存储任何动画的目标值的模型对象。每当更改图层的属性时都使用其中一个对象。模型树负责存储动画的目标值的模型对象。每当更改图层的属性时它都会把数据存储下来。
模型树的背后还存在两份图层树的拷贝一个是呈现树Presentation Tree一个是渲染树Render Tree。呈现树可以通过普通layer(其实就是模型树)的layer.presentationLayer获得,而模型树则可以通过modelLayer属性获得。呈现树通过图层树中所有图层的呈现图层所形成。注意呈现图层仅仅当图层首次被提交就是首次第一次在屏幕上显示的时候创建所以在那之前调用-presentationLayer将会返回nil。呈现树中的对象反映屏幕上显示的当前值。您永远不应该修改此树中的对象。相反您可以使用这些对象来读取当前动画值也许是为了从这些值开始创建新动画。self.layer self.layer.modelLayer 、self.layer ! self.layer.presentationLayer。layer本身其实就是一个模型layer只不过它拥有presentationLayer。
呈现树的属性值和动画运行过程中界面上看到的是一致的而渲染树是私有的是对呈现树的数据进行渲染。为了不阻塞主线程渲染的过程是在单独的进程或线程中进行的。 property(nonatomic,readonly,retain) CALayer *layer; // 通过UIView的layer属性可以访问这个层 UIView与CALayer
当UIView需要显示时会调用drawRect:方法将所有内容绘制在自己的CALayer上绘图完毕后系统再将图层拷贝到屏幕上从而完成了UIView的显示。UIView的animation实现的动画本质上也是通过CALayer来实现的iOS系统中CALayer的很多属性都是隐含有动画效果的如果不想要隐式动画或者想要显示动画效果都可以通过CATransaction来设置是否显示动画效果。同时在CATransaction内可同时修改多个属性然后再一并同时渲染另外CATransaction还是可嵌套的。与CALayer相比UIView还具有事件处理的功能可以跟用户进行交互。CALayer的性能更高因为它不具备处理事件和响应链responder chain等CALayer直接继承于NSObject而UIView继承于UIResponder更加轻量级。UIView侧重于对显示内容的管理CALayer侧重于对内容的绘制。对于UIView所管理的内容显示任何图形都会受到CALayer的影响。UIView依赖于CALayer提供的内容CALayer依赖于UIView提供的容器来显示绘制的内容。UIView与CALayer都有树状层级结构CALayer内部有SubLayersUIView内部也有SubViews。
CALayer重要属性 属性 作用 position 设置CALayer在父层上的位置以父层的左上角为原点(0,0) anchorPoint 决定CALayer哪个点会在position属性指定的位置以自己的左上角为原点(0,0)最大的坐标位置为右下角为(1,1)其默认位置为中心点(0.5,0.5) bounds 设置CALayer对象的尺寸
隐式动画
每一个UIView内部都默认关联着一个CALayer我们可称这个Layer为Root Layer根层。所有的非Root Layer的显式CALayer对象都存在隐式动画。当对显式CALayer对象的部分属性进行修改时默认会自动产生一些动画效果, 这些属性称为Animatable Properties。 // 通过动画事务(CATransaction)关闭默认的隐式动画效果
[CATransaction begin];
[CATransaction setDisableActions:YES];
self.myview.layer.position CGPointMake(10, 10);
[CATransaction commit]; 常见Animatable Properties 属性 作用 bounds 用于设置CALayer的宽度和高度修改这个属性会产生缩放动画 backgroundColor 用于设置CALayer的背景色修改这个属性会产生背景色的渐变动画 position 用于设置CALayer的位置修改这个属性会产生平移动画
3.2 Core Animation IOS 动画主要是指Core Animation框架。官方使用文档地址为Core Animation Programming Guide。Core Animation是IOS和OS X平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数如开始点的位置和结束点的位置即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑不会加重CPU的负担而影响程序的运行速度。 Core Animation核心动画是一组iOS提供的动画处理API它是跨Mac OS X和iOS平台的。Core Animation的动画执行过程都是在后台操作的不会阻塞主线程。Core Animation作用于CALayer上而并非UIView修改的值都是假象layer的真实位置并没有发生改变。 类 作用 CABasicAnimation 基本动画。CABasicAnimation有三个比较重要的属性fromValue、toValue、byValue这三个属性都是可选的但不能同时多于两个为非空最终都是为了确定animation变化的起点和终点。设置了动画的起点和终点之后中间的值都是通过插值方式计算出来的插值计算的结果由timingFunction指定默认timingFunction为nil会使用liner的也就是变化是均匀的。 CAKeyframeAnimation 帧动画。任何动画要表现出运动或者变化,至少需要两个不同的关键状态,而中间的状态的变化可以通过插值计算完成,从而形成补间动画,表示关键状态的帧叫做关键帧.CABasicAnimation其实可以看作一种特殊的关键帧动画,只有头尾两个关键帧.CAKeyframeAnimation则可以支持任意多个关键帧,关键帧有两种方式来指定,使用path或者使用values,path是一个CGPathRef的值,且path只能对CALayer的 anchorPoint 和 position 属性起作用,且设置了path之后values就不再起效了.而values则更加灵活. keyTimes这个可选参数可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的. 还可以通过设置可选参数timingFunctions(CAKeyframeAnimation中timingFunction是无效的)为关键帧之间的过渡设置timingFunction,如果values有n个元素,那么timingFunctions则应该有n-1个.但很多时候并不需要timingFunctions,因为已经设置了够多的关键帧了,比如没1/60秒就设置了一个关键帧,那么帧率将达到60FPS,完全不需要相邻两帧的过渡效果当然也有可能某两帧 值相距较大,可以使用均匀变化或者增加帧率,比如每0.01秒设置一个关键帧. 在关键帧动画中还有一个非常重要的参数,那便是calculationMode,计算模式.其主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorPoint 和 position 进行的动画.当在平面座标系中有多个离散的点的时候,可以是离散的,也可以直线相连后进行插值计算,也可以使用圆滑的曲线将他们相连后进行插值计算. calculationMode目前提供如下几种模式 kCAAnimationLinear kCAAnimationDiscrete kCAAnimationPaced kCAAnimationCubic kCAAnimationCubicPaced kCAAnimationLinear calculationMode的默认值,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算; kCAAnimationDiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示; kCAAnimationPaced 使得动画均匀进行,而不是按keyTimes设置的或者按关键帧平分时间,此时keyTimes和timingFunctions无效; kCAAnimationCubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,对于曲线的形状还可以通过tensionValues,continuityValues,biasValues来进行调整自定义,这里的数学原理是Kochanek–Bartels spline,这里的主要目的是使得运行的轨迹变得圆滑; kCAAnimationCubicPaced 看这个名字就知道和kCAAnimationCubic有一定联系,其实就是在kCAAnimationCubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keyTimes以及timingFunctions也是无效的. CATransition 转场动画。 CAAnimationGroup 动画组。 CAMediaTimingFunction 提供了两种获得时间函数的方式使用预定义的五种时间函数或通过给点两个控制点得到一个时间函数。有五种预定义的时间函数kCAMediaTimingFunctionLinear kCAMediaTimingFunctionEaseIn kCAMediaTimingFunctionEaseOut kCAMediaTimingFunctionEaseInEaseOut kCAMediaTimingFunctionDefault CADisplayLink 一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。一旦CADisplayLink以特定的模式注册到runloop之后每当屏幕需要刷新的时候runloop就会调用CADisplayLink绑定的target上的selector这时target可以读到 CADisplayLink 的每次调用的时间戳用来准备下一帧显示需要的数据。例如一个视频应用使用时间戳来计算下一帧要显示的视频数据。在UI做动画的过程中需要通过时间戳来计算UI对象在动画的下一帧要更新的大小等等。依托于设备屏幕刷新频率触发事件所以其触发时间上是最准确的。也是最适合做UI不断刷新的事件过渡相对流畅无卡顿感 仿射变换包括如下所有变换以及这些变换任意次序次数的组合平移、旋转、放缩、剪切、反射 /**
struct CATransform3D
{
CGFloat m11x缩放, m12y切变, m13旋转, m14;CGFloat m21x切变, m22y缩放, m23, m24;CGFloat m31旋转, m32, m33, m34透视效果要操作的这个对象要有旋转的角度否则没有效果。正直/负值都有意义;CGFloat m41x平移, m42y平移, m43z平移, m44;
};
**/ 总结CoreAnimation是跨iOS和macOS的CoreAnimation在后台执行动画而不阻塞主线程CoreAnimation作用于CALayer而不是UIView。
3.2.1 Core Graphics
Core Graphics是一个基于C的绘图专用的API族它经常被称为QuartZ或QuartZ 2D是一个二维绘图引擎同时支持iOS和macOS。它提供了低级别、轻量级、高保真度的2D渲染。该框架可以用于基于路径的绘图、变换、颜色管理、脱屏渲染模板、渐变。
iOS系统本身提供了两套绘图的框架即UIBezierPath和Core Graphics。前者所属UIKit其实是对Core Graphics框架关于path的进一步封装CoreGraphics是底层绘制框架我们实际会用到的也就是CG开头的一些底层绘制函数和变量这是一个纯C语言框架。使用UIBezierPath绘图只能在drawRect里进行因为底层要用到上下文图形上下文只能在drawRect里获取不能在其他方法里面绘图比如不能在awakeFromNib里绘图。
CoreGraphics和CoreAnimation它们都是跨iOS和Mac OS 使用的这点区别于UIKit并且CoreAnimation中大量使用到CoreGraphics中的类因为实现动画要用到图形库中的东西。
CGContextRef
图形上下文是一个CGContextRef类型的数据图形上下文相当于画板用于封装绘图信息(画了什么)和绘图状态(线条大小、颜色等)它决定绘制的输出目标(绘制到什么地方去)目标可以是PDF文件、bitmap或者显示器的窗口。在UIView中系统会默认创建一个Layer Graphics Context它对应UIView的layer属性该图形上下文可以在drawRect:方法中获取开发者只能获取不能自己重新创建在该图层上下文中绘制的图形最终会通过CALayer显示出来。因此View之所以能显示东西完全是因为它内部的layer。
当 UIView 需要显示时它内部的层会准备好一个 CGContextRef图形上下文然后调用 delegate这里就是 UIView的 drawLayer:inContext: 方法并且传入已经准备好的 CGContextRef 对象。而 UIView 在 drawLayer:inContext: 方法中又会调用自己的 drawRect: 方法。平时在 drawRect: 中通过 UIGraphicsGetCurrentContext() 获取的就是由层传入的 CGContextRef 对象在 drawRect: 中完成的所有绘图都会填入层的 CGContextRef 中然后被拷贝至屏幕。 5 AVPlayer
AVFoundation是一个功能齐全的高级框架用于在 iOS、macOS、watchOS 和 tvOS 上处理基于时间的视听媒体。通过开发所需的工具提供了强大的功能集让开发者能够基于苹果平台创建当下最先进的媒体应用程序其针对64位处理器设计充分利用了多核硬件优势会自动提供硬件加速操作确保大部分设备能以最佳性能运行。
AVFoundation的播放都围绕AVPlayer展开AVPlayer是一个用来播放基于时间的视听媒体的控制器对象。支持播放从本地、分布下载或通过HTTP Live Streaing协议得到的流媒体并在多种播放场景中播放这些资源。