IOS开发学习笔记

多线程的注意点
1.不要同时开太多的线程(1~3条线程即可,不要超过5条)
2.线程概念
1> 主线程 : UI线程,显示、刷新UI界面,处理UI控件的事件
2> 子线程 : 后台线程,异步线程
3.不要把耗时的操作放在主线程,要放在子线程中执行

一、NSThread
1.创建和启动线程的3种方式
1> 先创建,后启动
// 创建
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:nil];
// 启动
[thread start];

2> 创建完自动启动
[NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:nil];

3> 隐式创建(自动启动)
[self performSelectorInBackground:@selector(download:) withObject:nil];

2.常见方法
1> 获得当前线程
+ (NSThread *)currentThread;

2> 获得主线程
+ (NSThread *)mainThread;

3> 睡眠(暂停)线程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

4> 设置线程的名字
- (void)setName:(NSString *)n;
- (NSString *)name;

二、线程同步(掌握)
1.实质:为了防止多个线程抢夺同一个资源造成的数据安全问题

2.实现:给代码加一个互斥锁(同步锁)
@synchronized(self) {
    // 被锁住的代码
}

三、GCD
1.队列和任务
1> 任务 :需要执行什么操作
* 用block来封装任务

2> 队列 :存放任务
* 全局的并发队列 : 可以让任务并发执行
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

* 自己创建的串行队列 : 让任务一个接着一个执行
dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);

* 主队列 : 让任务在主线程执行
dispatch_queue_t queue = dispatch_get_main_queue();

2.执行任务的函数
1> 同步执行 : 不具备开启新线程的能力
dispatch_sync...

2> 异步执行 : 具备开启新线程的能力
dispatch_async...

3.常见的组合(掌握)
1> dispatch_async + 全局并发队列
2> dispatch_async + 自己创建的串行队列

4.线程间的通信(掌握)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   // 执行耗时的异步操作...
   
   
   dispatch_async(dispatch_get_main_queue(), ^{
       // 回到主线程,执行UI刷新操作
   });
});

5.GCD的所有API都在libdispatch.dylib,Xcode会自动导入这个库
* 主头文件 : #import <dispatch/dispatch.h>

6.延迟执行(掌握)
1> perform....
// 3秒后自动回到当前线程调用self的download:方法,并且传递参数:@"http://555.jpg"
[self performSelector:@selector(download:) withObject:@"http://555.jpg" afterDelay:3];

2> dispatch_after...
// 任务放到哪个队列中执行
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
double delay = 3; // 延迟多少秒
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{
    // 3秒后需要执行的任务
});

7.一次性代码(掌握)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 这里面的代码,在程序运行过程中,永远只会执行1次
});

四、NSOperation和NSOperationQueue
1.队列的类型
1> 主队列
* [NSOperationQueue mainQueue]
* 添加到"主队列"中的操作,都会放到主线程中执行

2> 非主队列
* [[NSOperationQueue alloc] init]
* 添加到"非主队列"中的操作,都会放到子线程中执行

2.队列添加任务
* - (void)addOperation:(NSOperation *)op;
* - (void)addOperationWithBlock:(void (^)(void))block;

3.常见用法
1> 设置最大并发数
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

2> 队列的其他操作
* 取消所有的操作
- (void)cancelAllOperations;

* 暂停所有的操作
[queue setSuspended:YES];

* 恢复所有的操作
[queue setSuspended:NO];

4.操作之间的依赖(面试题)
* NSOperation之间可以设置依赖来保证执行顺序
* [operationB addDependency:operationA];
// 操作B依赖于操作A,等操作A执行完毕后,才会执行操作B
* 注意:不能相互依赖,比如A依赖B,B依赖A
* 可以在不同queue的NSOperation之间创建依赖关系

5.线程之间的通信
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
    // 1.执行一些比较耗时的操作
   
    // 2.回到主线程
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
       
    }];
}];

五、从其他线程回到主线程的方式
1.perform...
[self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

2.GCD
dispatch_async(dispatch_get_main_queue(), ^{

});

3.NSOperationQueue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
   
}];

六、第三方框架的使用建议
1.用第三方框架的目的
1> 开发效率:快速开发,人家封装好的一行代码顶自己写的N行
2> 为了使用这个功能最牛逼的实现

2.第三方框架过多,很多坏处(忽略不计)
1> 管理、升级、更新
2> 第三方框架有BUG,等待作者解决
3> 第三方框架的作者不幸去世、停止更新(潜在的BUG无人解决)
4> 感觉:自己好水

3.比如
流媒体:播放在线视频、音频(边下载边播放)
非常了解音频、视频文件的格式
每一种视频都有自己的解码方式(C\C++)

4.总结
1> 站在巨人的肩膀上编程
2> 没有关系,使劲用那么比较稳定的第三方框架

七、SDWebImage的图片下载
1.面试题
1> 如何防止一个url对应的图片重复下载
* “cell下载图片思路 – 有沙盒缓存”

2> SDWebImage的默认缓存时长是多少?
* 1个星期

3> SDWebImage底层是怎么实现的?
* 上课PPT的“cell下载图片思路 – 有沙盒缓存”

2.SDWebImage
1> 常用方法
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

2> SDWebImageOptions
* SDWebImageRetryFailed : 下载失败后,会自动重新下载
* SDWebImageLowPriority : 当正在进行UI交互时,自动暂停内部的一些下载操作
* SDWebImageRetryFailed | SDWebImageLowPriority : 拥有上面2个功能


sudo chmod u+x 文件名
sudo chmod 700 文件名
sudo chmod 777 文件名


地图定位

CoreLocation

CLLocation *bjLoc  Latitude 39.54 longitude:116.28

CLLocation *bjLoc  Latitude 23.05 longitude:113.15



1、CoreLocation
*CLLocationManager局部变量不能定位

*模拟器不支持定位,要手动



代理

startUpdatingLocation

stopUpdatingLocation

locationManager:didUpdateLocations

a> *CLLocation 

b> *经纬度

    CLLocationCoordinate2D

c> *海拔

d> location.altitude

e> *速度

   location.speed

f> self.locManager.distanceFilter = 1000;

 //精确到1米 越精确精耗电

g> self.locManager.desiredAccuracy = 1;

*距离计算

CLLocation distanceFromLocation

广州 CLLocation *bjLoc  Latitude 39.54 longitude:116.28

北京 CLLocation *bjLoc  Latitude 23.05 longitude:113.15

*plist文件添加隐私描述

Privacy - Location Usage Description

计算两个经纬度间的直线距离



2、地理编码

CLGeocoder

>地理编码

*把地点名称解析成详细地理信息

self.geoCoder geocodeAddressString

placemarks放CLPlacemark(位置标记)

CLPlacemark里的属性成员

CLLocation *location = placeMark.location;

CLLocationCoordinate2D coordinate = location.coordinate;





注:longitude与latitude不要写错

>把地理位置解析成详细地理信息(116.35 40.16)

反地理编码

reverseGeocodeLocation



补充.

1.CLPlacemark的addressDictionary属性 遍历字典数据

addressDictionary enumerateKeysAndObjectsUsingBlock

2.block是在主线程调用,所以可以直接在block刷新UI

name                    :   地名
thoroughfare            :   街道
ubThoroughfare          :   街道相关信息,例如门牌等
locality                :   城市
subLocality             :   城市相关信息,例如标志性建筑
administrativeArea      :   直辖市
subAdministrativeArea   :   其他行政区域信息
postalCode              :   邮编
ISOcountryCode          :   国家编码
country;                :   国家
inlandWater             :   水源、湖泊
ocean;                  :   海洋
areasOfInterest         :   关联的或利益相关的地标



MapKit

1.MapKit使用的基本使用

*创建项目

添加框架

导入MapKit

运行项目





*设置mapType地理显示类型

*设置跟踪模式userTrackingMode

*设置代理

didUpdateUserLocation方法



大头针userLocation.title = @"北京";

位置信息userLocation.coordinate

显示居中mapView setCenterCoordinate

显示区域 mapView setRegion



regionDidChangeAnimated方法



*返回原点





2.大头针(随机添加)

*添加tap手势

*获取点位置转成mapView的地理位置

mapview的点转成经纬度

[self.mapView convertPoint:tapPoint toCoordinateFromView:tap.view]

*添加CZAnnotation实现MKAnnotation代理



*随机添加20个头针

在触摸点的位置随机添加20个位置arc4random_uniform(100)/ 1000.0







3.自定义大头针



传智地址 经度:116.3544839331055纬度:40.06214218062825



>

*自定义一个Tuangou大头针模型,先不要加图片属性

*touch的时候添加大头针

引出下面两个代理方法



mapView:viewForAnnotation(大头针模型)

返回nil时,系统会自己添加大头针



mapView:didAddAnnotationViews(大头什视图)

MKModernUserLocationView(用户无法用,苹果私有api)

MKPinAnnotationView

返回大头针



从缓存池里取(与tableView一样取法)



自己实现MKPinAnnotationView,要想显示标题与子标题,得设置pinView的canShowCallout canShowOffset



属性为YES



*实现从天而降效果animatesDrop

*pinColor别针颜色(枚举)

注:要写return pinView;

>直接让购View返回的是MKAnnotationView



然后在团购模型中添加图片

设置canShowCallout为YES

设置annoView.image改变大头针图片

设置calloutoffset = CGPointMake(0,-10)

*添加右边rightCalloutAccessoryView

*添加左边leftCalloutAccessoryView



4.自定义大头针描述

150 x 80

选添加团购大头针

再添加团购描述大头针



5.画线路

跟大头针一样 

//方向对象

addOverlay

MKPolyline

MKPolylineRenderer

//计算路线
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
   
 //设置起点
MKPlacemark *fromPm = [[MKPlacemark alloc] initWithPlacemark:from];
request.source = [[MKMapItem alloc] initWithPlacemark:fromPm];
   
 //设置终点
MKPlacemark *toPm = [[MKPlacemark alloc] initWithPlacemark:to];
request.destination = [[MKMapItem alloc] initWithPlacemark:toPm];

MKDirections *directions = [[MKDirections alloc] initWithRequest:request];

  //计算路线

  [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {       

        NSLog(@"共有几条路线 %d",response.routes.count);

        for (MKRoute *route in response.routes) {

            [self.mapView addOverlay:route.polyline];

        }

    }];



-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{

    MKPolylineRenderer *render = [[MKPolylineRenderer alloc] initWithOverlay:overlay];

    render.strokeColor = [UIColor blueColor];

   render.lineWidth = 5

    return render;

}





6.使用系统的地图导航

[self.geocoder geocodeAddressString:@"广州" completionHandler:^(NSArray *placemarks, NSError *error) {

 MKMapItem *currentItem = [MKMapItem mapItemForCurrentLocation];

 CLPlacemark *gzCLPM = [placemarks lastObject];

 MKPlacemark *gzMKPM = [[MKPlacemark alloc] initWithPlacemark:gzCLPM];

 MKMapItem *destItem = [[MKMapItem alloc] initWithPlacemark:gzMKPM];

       

 NSMutableDictionary *options = [NSMutableDictionary dictionary];

options[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;//行车路线

options[MKLaunchOptionsShowsTrafficKey] = @YES;

 options[MKLaunchOptionsMapTypeKey] = [NSNumber numberWithInt:MKMapTypeSatellite];

 [MKMapItem openMapsWithItems:@[currentItem,destItem] launchOptions:options];

    }];


你可能感兴趣的:(IOS开发学习笔记)