菜鸟目录(一些常用知识点)

1.写项目之前首先我们要确定需求,明确项目需要实现哪些功能(吐槽下:好多项目的大部分功能都是一样的)

2,美工,后台啥的我都直不一一说了情况都不一样

废话不说了直接开写程序
很重要(1)首先我们要确定明确开发需要的框架,一个好的框架可以让我们轻松很多
  
框架可以自己写,也可以从网上找,多对比一下会有惊喜的
页面
(1)一般每个详情页面都有相应的导航栏;如果有直接参考(见导航Deno,直接输入图片网址或者本地图片,设置坐标一键搞定);如果没有直接跳过
(2)然后就到了图文布局了:(推荐xib或storyboard)强大快速(尤其项目比较急的时候更是不二选择);不熟练的话那就老实的算坐标,布局吧!这个情况太多,一般难度也不大,费点心基本都可以搞定(我在这里就不详细说了。)
我这里就按功能说了(不需要就直接跳过)
功能
搜索
第一种搜索:
UISearchBar   遵守协议
//将要进入编辑模式调用
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
//显示cancel 按钮
    [searchBar setShowsCancelButton:YES animated:YES];
    return YES;

}
//将要退出编辑模式调用
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
1
请把代码粘贴在这里

    //隐藏cancel 按钮
    [searchBar setShowsCancelButton:NO animated:YES];
    return YES;
}

// 点击 搜索按钮的时候调用
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    //写入搜索内容(根据需要进行搜索)

}
//点击cancel 被调用
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
   //清空内容
    searchBar.text = @"";
    [searchBar resignFirstResponder];//收键盘

}
第二种搜索
iOS8新出的感觉很强大,大家以后尽量都用它吧,紧跟版本呀!
  UISearchController :它的其中一个属性就是searchBar
需要先设置它的搜索结果视图
//nil为和当前视图总用一个视图
self.searchVC = [[UISearchController alloc] initWithSearchResultsController:nil];
//如果不需要刻意再创建一个如:
UITableViewController *tableVC = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
    
    tableVC.tableView.delegate = self;
    tableVC.tableView.dataSource = self;
    [tableVC.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
self.searchVC = [[UISearchController alloc] initWithSearchResultsController:tableVC];

注意需要两个协议
//搜索协议
delegate
//更新搜索内容的代理
searchResultsUpdater
//必须要加上 自适应才能显示 搜索条
[self.searchVC.searchBar sizeToFit];
UISearchResultsUpdating 协议
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSLog(@"searchBar 更新内容");
//搜索内容
    //检索推荐谓词检索,快准狠有没有!详细的去百度吧度娘威武!

  //最后搜索数据源变了  ->让搜索控制器 内部的结果视图控制器的tableView的刷新
    UITableViewController *tableVC = (UITableViewController *)searchController.searchResultsController;
    [tableVC.tableView reloadData];
}
- (void)willPresentSearchController:(UISearchController *)searchController {
    NSLog(@"searchController 将要 显示");
  
}
- (void)didPresentSearchController:(UISearchController *)searchController {
    NSLog(@"searchController 已经 显示");
}
- (void)willDismissSearchController:(UISearchController *)searchController {
    NSLog(@"searchController 将要 消失");
}

- (void)didDismissSearchController:(UISearchController *)searchController {
    NSLog(@"searchController 已经 消失");
}
!!如果需要页面跳转
在进行页面跳转的时候要注意现在有两个视图呀需要区分开
UIViewController *vc = nil;
    //self.presentedViewController获取已经模态跳转上册的视图控制器,如果dismiss 之后 这个值会变成nil
    if (self.presentedViewController) {
        //判断一下 当前视图控制器有没有 模态跳转 的视图,如果有 那么 做另外一个模态跳转的时候 应该用 上一个已经模态跳转的控制器进行 模态跳转下一个
        vc = self.presentedViewController;
    }else {
        vc = self;
    }
    //模态跳转
    [vc presentViewController:alert animated:YES completion:nil];

下载
首先判断是否已经下载过,然后告知服务器从哪里下载,
   (1)下载前需要先确定路径
获取文件在沙盒中Documents下的全路径
//我们把url作为文件名字-》但是url 中可能存在一些非法字符不能作为文件名,这时我们可以用md5 对文件名进行加密 产生一个唯一的字符串 (十六进制的数字+A-F表示),这样就可以保证文件名不出现非法字符
   NSString *fileName = [url MD5Hash];//MD5
    //获取Documents
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    //拼接路径
    NSString *filePath = [docPath stringByAppendingPathComponent:fileName];
    NSLog(@"path:%@",filePath);
***这里需要用到OC文件管理的知识!
//创建文件(首先检测有没有存在,如果没有在创建)
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        //检测文件是否存在
        //不存在那么要创建
                   //NSFileManager 文件管理句柄
        [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
    }
//如果已存在获取已近下载的大小,如果不存在那么大小为0;  
      NSDictionary *fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
   //保存已经下载文件的大小
    self.loadedFileSize = fileSize;
   //下载前需要打开文件
    self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
*****(如果服务器支持可变断点续传可以照用,如果不支持请忽略 头域)
   //把文件大小告知服务器
    //创建可变请求 增加请求头
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    //增加头域 告知服务器 从 哪个字节之后开始下载(不了解头域的还是那句话百度),不支持头域的可以直接跳过
    [request addValue:[NSString stringWithFormat:@"bytes=%llu-",fileSize] forHTTPHeaderField:@"Range"];
    //创建请求连接 开始异步下载
    _httpRequest = [[NSURLConnection alloc] initWithRequest:request delegate:self];
   NSURLConnectionDataDelegate
//接收服务器响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
在这里我们可以计算文件的总大小,获取数据的类型 : httpResponse.MIMEType ,数据的大小: NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response
NSLog(@"url:%@",httpResponse.URL.absoluteString);
//计算文件总大小 = 已经下载的+服务器将要发的
     ( self.loadedFileSize和上面关联着  数据是一段一段下载的)
    self.totalFileSize = self.loadedFileSize+httpResponse.expectedContentLength;
}
//接收数据过程 一段一段接收
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    //都是OC文件管理的知识,我就不细说了吧
    //下载一段 写一段数据
    //先把文件偏移量定位到文件尾
    [_fileHandle seekToEndOfFile];
    //写文件
    [_fileHandle writeData:data];
    //立即同步到磁盘
    [_fileHandle synchronizeFile];
    //记录已经下载数据大小
    self.loadedFileSize += data.length
}
//下载完成一定要关闭呀
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self stopDownload];//停止下载
}
//下载失败也要关闭呀
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self stopDownload];
}
- (void)stopDownload {
    if (_httpRequest) {
        [_httpRequest cancel];
        _httpRequest = nil;
    }
    [_fileHandle closeFile];//关闭文件
}
收藏(关注)
这和数据库有关联(数据库下面我会说的,不懂得也可以先看后面的数据库)
点击收藏按钮的时候相当于在数据库里面增加了一条数据
和关注按钮基本一样,有时候只是表现形似不同罢了本质都是一样
这里我用的是DBManager
//关于数据库的方法,自己写的,就是这里面记录的都是收藏过得数据
//获取所有的收藏过得数据,放在数组里
self.favoriteArr = [[DBManager sharedManager]fetchall];
然后遍历数组获取相关图片的的URL下载图片
for (int i = 0; i<_self.favoriteArr.count; i++) {
    AppModel *model = _favoriteArr;
//我这里建个button 来显示收藏(具体问题具体分析说白了就是把你收藏的东西展现出来)图片下载用的是SDimage第三方库
     UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn sd_setImageWithURL:[NSURL URLWithString:model.iconUrl] forState:UIControlStateNormal placeholderImage:[UIImage imageNamed: @"account_candou"]];



}
登录和注册(每个App必备的功能)

分为 ,自身登录*注册(自己起的名字知道大概意思就行了哈,别在意哈) 和 第三方登录(微博,QQ,微信,等外国的不常用,基本就是那几个社交的,忘了还有人人(话说没多少人用了吧),第三方遵循的基本原则:那个人多就用那个)
主要说下自身登录*注册
大多数登录和注册都用的是post请求{这里需要我们和做服务器的协调好,登陆成功,登录失败返回什么
我们根据这些来提示用户是否登陆成功,!
如果用户登录成功我们需要记录用户登录成功这个状态,以防止用户多次登录,重复登录
这时我们需要定义一个全局变量
在登录成功后记录登录状态

extern:引入外部变量
extern BOOL isLogin;
                isLogin=YES;

在其他页面再需要登录的先判断登录状态,如果为YES就不需要在登陆了,如果没有提示用户需要登录后才可以进入
}
第三方登录直接到开放平台下demo;


清除缓存

这里我用的SDimage库的
#import "UIImageView+WebCache.h"
-(double)getCachesSize
{
//SDimage缓存
NSInteger sdfileSize=[[SDImageCache sharedImageCache]getSize];   NSString*caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    NSString*mycacehs=[caches stringByAppendingPathComponent:@"MyCaches"];
    NSDirectoryEnumerator*enumor=[[NSFileManager defaultManager]enumeratorAtPath:mycacehs];
    NSUInteger mysize=0;
    for (NSString *filename in enumor) {
        NSString*filepath=[mycacehs  stringByAppendingPathComponent:filename];
        NSDictionary*filedict=[[NSFileManager defaultManager]attributesOfItemAtPath:filepath error:nil];
      //自身缓存
        mysize+=filedict.fileSize;
    }
    return (mysize+sdfileSize)/1024.0/1024.0;
}
分享
:(系统的和第三方的: 第三方的推荐友盟(简单呀两句话sdk:直接抄不用改省事哈哈,不过就一个微博可以用,如果想用QQ,微信,等,自有大家蛋疼的去对着文档来吧,))
系统的:
协议:MFMessageComposeViewControllerDelegate(信息),MFMailComposeViewControllerDelegate(邮箱)
1(信息)

//需要真机,虚拟机没效果
  if ([MFMessageComposeViewController canSendText]) {
//检测 当前应用 是否支持短信功能
   //支持的话 创建  具有短信模块的界面
MFMessageComposeViewController *message = [[MFMessageComposeViewController alloc] init];
                //设置联系人 (可以群发)
                message.recipients = @[@"10086",@"10011"];
                //设置短信的内容
                message.body = [NSString stringWithFormat:@"快来下载,这里有惊喜:%@“,@“网址”];
                   message.messageComposeDelegate = self;
                //模态跳转(内部有导航)
                [self presentViewController:message animated:YES completion:nil];

}
//协议
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
    switch (result) {
        case MessageComposeResultCancelled:
        {
            NSLog(@"取消");
        }
            break;
        case MessageComposeResultSent:
        {
            NSLog(@"短信已发送");
        }
            break;
        case MessageComposeResultFailed:
        {
            NSLog(@"短信失败");
        }
            break;
            
        default:
            break;
    }
    //最后要模态跳转返回
    [controller dismissViewControllerAnimated:YES completion:nil];
}
(2)邮箱
if ([MFMailComposeViewController canSendMail]) {
                //检测是否支持邮箱功能
                //如果支持 创建界面
                MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
                //设置联系人
                [mail setToRecipients:@[@"xxxxx@qq.com”,@“zzzz@163.com"]];
                //设置抄送
                [mail setCcRecipients:@[@"xxx@sina.com"]];
                //设置标题
                [mail setSubject:@"分享爱限免应用"];
                //设置内容
                NSString *str = [NSString stringWithFormat:@"点击有惊喜:%@“,@“网址”];
                //第二个参数 是否以HTML格式
                [mail setMessageBody:str isHTML:YES];
                
                //添加附件
                NSData *data = UIImagePNGRepresentation([UIImage  imageNamed: @"account_candou"]);
                //第一个参数 文件二进制  2 文件的类型 3  文件的名字
                [mail addAttachmentData:data mimeType:@"image/png" fileName:@"account_candou"];
                
                //设置代理
                mail.mailComposeDelegate = self;
                //模态跳转
                [self presentViewController:mail animated:YES completion:nil];
            }

//协议
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    switch (result) {
        case MFMailComposeResultCancelled:
            NSLog(@"邮件取消");
            break;
        case MFMailComposeResultSaved:
            NSLog(@"邮件保存");
            break;
        case MFMailComposeResultSent:
            NSLog(@"邮件发送");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"邮件失败");
            break;
            
        default:
            break;
    }
    //模态跳转返回
    [self dismissViewControllerAnimated:YES completion:nil];
}
//友盟的(不懂可以看官网)建立使用UM的 ,系统的太坑了,在咱们这没人用呀
//协议
UMSocialUIDelegate
[UMSocialSnsService presentSnsIconSheetView:self appKey:@"507fcab25270157b37000010" shareText:str  shareImage:[UIImage imageNamed: @"account_candou"] shareToSnsNames:[NSArray arrayWithObjects:UMShareToSina,UMShareToSms,UMShareToEmail,UMShareToWechatTimeline,nil] delegate:self];(写了这么多也就前三个有用微信需要自己去注册)
在appdelgete.m中(其他的,哎都是泪看文档把,你妹的呀)
//初始化UM
- (void)initUM {
    
    //初始化
     [UMSocialData setAppKey:@"507fcab25270157b37000010"];
}
地图
又到了都是泪的地方,文档走起吧,大苹果太渣
推荐百度,高德,腾讯(百度最好,但是那啥注册一把泪呀)
(1)定位:
//1.头文件
#import <CoreLocation/CoreLocation.h>
协议 CLLocationManagerDelegate
//必须要强引用 在定位之前不能释放
@property (nonatomic,strong) CLLocationManager *manager;
  kCLLocationAccuracyBestForNavigation   -->最好的精度 用于导航
  kCLLocationAccuracyBest;//精度高的
  kCLLocationAccuracyNearestTenMeters;   10m
  kCLLocationAccuracyHundredMeters;  100m
  kCLLocationAccuracyKilometer;    1000m
  kCLLocationAccuracyThreeKilometers;  3000m
   //精度越高 越耗电
- (void)initLocationManager {
    //用的时候才创建 懒加载
    if (!self.manager) {
        //实例化 管理器
        self.manager = [[CLLocationManager alloc] init];
        //设置精度类型
        self.manager.desiredAccuracy = kCLLocationAccuracyBest;
        //设置 精度的大小
        self.manager.distanceFilter = 10;
        //获取定位的数据 必须要设置代理
        self.manager.delegate = self;
        //iOS8之后 必须要向用户申请授权
        /*
         1.在Info.plist中 添加选项
            Privacy - Location Usage Description(可选)
            NSLocationAlwaysUsageDescription(和代码要对应)
            或者
            NSLocationWhenInUseUsageDescription(代码要对应)
         2.在代码中 添加
            [self.manager requestAlwaysAuthorization];
            或者
            [self.manager requestWhenInUseAuthorization];
         */
        
        double v = [UIDevice currentDevice].systemVersion.doubleValue;
        if (v >= 8.0) {//判断版本
            //设置一个就可以
            //始终允许授权打开定位 (前后台都允许)
            [self.manager requestAlwaysAuthorization];
            //使用的时候允许 (前台允许)
            //[self.manager requestWhenInUseAuthorization];//
            //允许之后 第一次 会弹出一个警告框 选择允许
        }
        //下面的条件编译也可以 判断当前系统 版本
#ifdef __IPHONE_8_0 //如果定义过这个宏__IPHONE_8_0,iOS8.0之后就会定义宏__IPHONE_8_0  
        
#endif
        
    }
}
//开始定位
- (void)startLocation:(UIBarButtonItem *)item {
    //判断是否具备定位功能
    if ([CLLocationManager locationServicesEnabled]) {
        //懒加载管理器
        [self initLocationManager];
        //开始定位
        [self.manager startUpdatingLocation];
    }
}
//停止定位
- (void)stopLocation:(UIBarButtonItem *)item {
    [self.manager stopUpdatingLocation];
}
定位协议
//当定位的位置 发生改变的时候 一会一直调用
//会把定位的地理位置 传入
//locations 存放的就是地理位置
//数组中就一个元素
//
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    if (locations.count) {
        //获取定位 位置
        CLLocation *location = [locations lastObject];
        //得到经纬度
        CLLocationCoordinate2D coordinate = location.coordinate;
        //打印经纬度
        NSLog(@"location:%f %f",coordinate.longitude,coordinate.latitude);
        //地理反编码
    //把经纬度装化为具体的地址    
#if 0
        [self reverseGeocoderWithBaidu:coordinate];
#else
        [self reverseGeocoderWithSystem:location];
#endif
        
        
    }
}
//百度的
//需要OCJson解析
- (void)reverseGeocoderWithBaidu:(CLLocationCoordinate2D)coordinate {
    //用多线程 异步下载
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:kPathUrl,coordinate.latitude,coordinate.longitude]]];
        //json解析
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSDictionary *resultDict = dict[@"result"];
        NSLog(@"address:%@",resultDict[@"formatted_address"]);//获取地址
        
    });
}
//系统 地理反编码
- (void)reverseGeocoderWithSystem:(CLLocation*)location {
    //创建对象
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    //根据location内部的经纬度 进行 地理反编码
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        //placemarks  我们要的反编码信息
        for (CLPlacemark *placemark in placemarks) {
            NSLog(@"country:%@",placemark.country);
            NSLog(@"name:%@",placemark.name);
            //遍历地址字典
            for (NSString *key in placemark.addressDictionary) {
                NSLog(@"%@",placemark.addressDictionary[key]);
            }
        }
    }];
    
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"定位失败");
}

(2)导航:在定位的基础的延伸
(3)查询:在定位的基础的延伸
(4)地图:

我把系统的说了,其他的百度和高德,腾讯的自己下()
和定位很类似
#import <MapKit/MapKit.h>
协议
MKMapViewDelegate
@property (nonatomic, strong) MKMapView *mapView;//地图
(void)initMapView {
    [self initManager];//需要定位 就调用
    
    //实例化 地图
    self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
    self.mapView.mapType = MKMapTypeStandard;
    //设置地图显示的 区域 (给一个中心位置)
    // 给一个 经纬度 和 缩放比例(0.01---0.05)
    //34.77274892, 113.67591140
    self.mapView.region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(34.77274892, 113.67591140),MKCoordinateSpanMake(0.01, 0.01));
    //是否显示 用户位置
    self.mapView.showsUserLocation = YES;
    
    //设置代理
    self.mapView.delegate = self;//可以操作点标注
    
    //粘贴地图
    [self.view addSubview:self.mapView];
    
    //增加大头针(需要就创建不需要可以无视)
    [self createAnnotation];

}

协议方法
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {

if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
        //判断是哪一类点标注数据
        //创建 点标注视图 (采用复用机制)
        //队列获取空闲的
        MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"MKPinAnnotationView"];
        if (pinView == nil) {
            //没有那么创建新的
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MKPinAnnotationView"];
        }
     //设置属性(不需要的可以不设置)
        //是否显示气泡
        pinView.canShowCallout = YES;
        //是否有掉落的动画
        pinView.animatesDrop = YES;//(点标注视图子类MKPinAnnotationView才可以设置)
        //设置大头针视图的颜色  红  绿  紫三种
        pinView.pinColor =  MKPinAnnotationColorPurple;
        
        //设置气泡的左右侧附件
        UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
        redView.backgroundColor = [UIColor redColor];
        pinView.leftCalloutAccessoryView = redView;
        
        UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoLight];
        button.frame = CGRectMake(0, 0, 30, 30);
        //气泡附件 如果是UIControl的子类 不需要再增加事件,有一个协议的方法可以替代
        //[button addTarget:<#(id)#> action:<#(SEL)#> forControlEvents:<#(UIControlEvents)#>];
        pinView.rightCalloutAccessoryView = button;
        return pinView;//返回对象地址
    }
}
如果需要的还可以添加手势
- (void)createLongPress {
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    [self.mapView addGestureRecognizer: longPress];
}
根据手势做出不同的调用
- (void)longPress:(UILongPressGestureRecognizer *)press {

}
数据库
sqlite(一般我们不直接向数据库进行操作,使用 第3方库来操作数据库,方便快速,但不能认为这些库就能存储数据,简单点理解这玩意就是中介)
常用的有FMDB(开源库)  coredata(官方系统库)
常用的数据库操作,增删改查
首先导入第三方库FMDB
封装一个类来管理数据库
方法:
代码操作数据库 用fmdb 第三库操作 sqlite
fmdb 就是 通过对C语言的底层函数封装 对 数据库进行创建 增删改查数据

步骤
1.导入fmdb
2.导入libsqlite3.dylib
3.导入头文件  #import "FMDatabase.h"
4. 创建 数据库
    4.1打开数据库 创建表
    4.2 增删改查数据  代码执行sql 语句
//导入头文件
#import "FMDatabase.h"
创建数据库
- (void)createDataBase {
//沙盒路径
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    //拼接 数据库的路径后面的数据库的名字
    NSString *dataPath = [docPath stringByAppendingPathComponent:@"myData.sqlite"];
    //实例化一个 fmdb 对象
    NSLog(@"%@",dataPath);
    _database = [[FMDatabase alloc] initWithPath:dataPath];
    
    //如果打开成功 返回yes
    //调用open 的时候 如果数据库不存在那么就会先创建再打开,如果存在直接打开
    if ([_database open]) {//打开数据库
        //打开成功之后创建表
        [self createTable];
    }else{
        NSLog(@"open error:%@",[_database lastErrorMessage]);//最近一次错误
    }
    //数据库 一般 只打开一次  这样可以提高效率
}
创建表格
//其实的在数据库里面创建表是一样只不过用库来代创建方便(和用中介找房子一样的)
//user是表名(后面的表的属性)
- (void)createTable {
    NSString *sql = @"CREATE TABLE if not exists user (serial integer  Primary Key Autoincrement,num integer,name Varchar(256),mydate datetime,headimage blob)";
    //执行 sql 语句 成功返回yes 失败返回no
    BOOL isSuccess = [_database executeUpdate:sql];
    if (!isSuccess) {
        NSLog(@"create table error:%@",_database.lastErrorMessage);
    }
}
//增加数据
- (void)insertData {
    NSInteger num = arc4random()%69+1;
    NSString *name = [NSString stringWithFormat:@"xiaohong%u",arc4random()%100];
    //时间
    NSDate *date = [NSDate date];
    
    //图片要存成二进制
    NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed: @"0"]);
    //要用 ? 占位符 在sql 中 ? 表示的是对象的占位符
    // ?  对应的必须是一个 OC的对象的地址
    
    //增加 sql 语句
    NSString *sql = @"insert into user(num,name,mydate,headimage) values (?,?,?,?)";
    
    //执行sql
    BOOL isS = [_database executeUpdate:sql,@(num),name,date,imageData];
    if (!isS) {
        NSLog(@"insert into error :%@",_database.lastErrorMessage);
    }
}
//查询
- (void)fetchAllData{
    //1.sql
    NSString *sql = @"select num,name,mydate,headimage from user";
    //2.执行
    //会返回一个结果集合 查找的结果都在 FMResultSet中
    FMResultSet *rs = [_database executeQuery:sql];
    //遍历集合
    while ([rs next]) {//表示 FMResultSet中还有没有记录
        NSInteger num = [rs intForColumnIndex:0];//根据字段索引获取值
        NSInteger num2 = [rs intForColumn:@"num"];//根据字段名字获取值
        NSLog(@"num:%ld num2:%ld",num,num2);
        NSLog(@"name:%@",[rs stringForColumn:@"name"]);
        NSLog(@"date:%@",[rs dateForColumn:@"mydate"]);
        NSLog(@"image_length:%ld",[rs dataForColumn:@"headimage"].length);
        NSLog(@"-------------------------------");
        //[rs objectForColumnName:<#(NSString *)#>];//通用
    }
    //第一循环 遍历第0条记录
    //第二循环      1
    //...
    //直到最后没有了记录 循环退出
    
}
//更新数据
-(void)updateData
{
    NSString*sql=@"update user name=? where num<50 ";
    if ([_database executeUpdate:sql,@"小红" ]) {
        NSLog(@"updata error:%@",_database.lastErrorMessage);
    }
}
//删除数据
-(void)deletedatawithNUm:(NSInteger)num
{
    NSString*sql=@"delete from user where num=?";
    if ([_database executeUpdate:sql,@(num)]) {
        NSLog(@"%@",_database.lastErrorMessage);
    }
}
coredata苹果官方的效果棒棒哒,也很好用

首先先右键—》newfile—> (iOS )core data—>DataModel  完成后会有类名.xcdatamodel文件,可视化操作,创建表(注意改下表名字,默认的有可能关联不上),然后在表里面添加属性,完成后右键—》newfile—> (iOS )core data—>NSManagerObject subclass ,然后和你的表关联一下model层就创建出来了,
下面就是封装一个类来专门管理coredata,方便我们对数据库尽心操作
导入头文件
#import <CoreData/CoreData.h>
/设计一个单例类 管理数据库
@interface CoreDataManager : NSObject
//非标准单例
+ (instancetype)defaultManager;

//上下文管理对象
@property (nonatomic,strong) NSManagedObjectContext *context;


//增删改查
//增加一个数据
- (void)insertDataWithName:(NSString *)name age:(int)age;

//根据名字删除
- (void)deleteDataWithName:(NSString *)name;

//修改数据 根据名字修改年龄
- (void)updateDataWithName:(NSString *)name age:(int)age;

//查询
//查询所有的数据
- (NSArray *)fetchAllData;

//根据名字查找
- (NSArray *)fetchDataWithName:(NSString *)name;

实现方法:
//(创建单例类的方法网上有好多)
+ (instancetype)defaultManager {
    static CoreDataManager *manager = nil;
    
    @synchronized(self) {
        manager = [[self alloc] init];
    }
    return manager;
}
//初始化准备工作
//1.导入头文件 CoreData/CoreData.h
//2.创建一个 一个数据模型文件(和数据库中的表类似),里面创建一些数据模型(设计属性)
//3.设计 一个数据模型类(根据数据模型文件)
//术语不明白的度娘走起(我就不唠叨了)
- (instancetype)init {
    if (self = [super init]) {
        //1.将数据模型文件中的 的模型 放入 modelFile 指向的 对象中
        //关联数据模型
         NSManagedObjectModel *modelFile = [NSManagedObjectModel mergedModelFromBundles:nil];

        //2.设置 存储 协调器  (协调 底层和上层)
        //2.1让 协调器 和 modelFile产生关联
        NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:modelFile];
        
        //2.2设置数据库文件的路径
        NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/Mydata.sqlite"];
        NSError *error = nil;
        //2.3设置 存储方式 根据路径创建 数据库文件
        ///将coreData数据  映射到数据库
        
        NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:path] options:nil error:&error];
        if (!store) {
            //创建 失败
            NSLog(@"creat store falied:%@",error.localizedDescription);
            return nil;
        }
        
        //3.托管对象 /上下文管理对象
        self.context = [[NSManagedObjectContext alloc] init];
        //托管对象 和 协调器 产生 关联
        self.context.persistentStoreCoordinator = coordinator;
        //_context 对数据库 进行增删改查
    }
    return self;
}
下面就是增删改查了
//增加一个数据
- (void)insertDataWithName:(NSString *)name age:(int)age {
    //1.给_context 操作的数据 增加一个UserModel实例对象
    
    //用 NSEntityDescription来增加
    UserModel *model = (UserModel *)[NSEntityDescription insertNewObjectForEntityForName:@"UserModel" inManagedObjectContext:self.context];
    model.name = name;
    model.age = @(age);
    model.fName = [name substringToIndex:1];
    
    //保存数据
    [self saveDataWithType:@"addData"];
}
- (void)saveDataWithType:(NSString *)type {
    NSError *error = nil;
    //回写 保存到数据库文件
    if (![self.context save:&error]) {
        //保存失败
        NSLog(@"%@:%@",type,error.localizedDescription);
    }
}
//根据名字删除
- (void)deleteDataWithName:(NSString *)name {
    //根据名字 找到对象
    NSArray *arr = [self fetchDataWithName:name];
    //遍历数组
    for (UserModel *model in arr) {
        [self.context deleteObject:model];
    }
    //保存数据
    [self saveDataWithType:@"deleteData"];
}
//修改数据 根据名字修改年龄
- (void)updateDataWithName:(NSString *)name age:(int)age{
    //1.根据名字 找到对象
    NSArray *arr = [self fetchDataWithName:name];
    //2.遍历数组
    for (UserModel *model in arr) {
        model.age = @(age);
    }
    //3.保存数据
    [self saveDataWithType:@"updateData"];

}
//查询
//查询所有的数据
- (NSArray *)fetchAllData {
    return [self fetchDataWithName:nil];
}
根据名字 在数据库中 查找 数据模型对象
//根据名字查找
- (NSArray *)fetchDataWithName:(NSString *)name {
    //1.先设置查找请求
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    //2.设置 查找的数据模型对象
    request.entity = [NSEntityDescription  entityForName:@"UserModel" inManagedObjectContext:_context];
    //3.设置 谓词 (根据条件 找要设置谓词)
    if (name) {
        //name 不是nil 那么就根据名字找 设置谓词
        //要查询 一个对象的 匹配的属性 那么需要设置谓词
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@",name];
        request.predicate = predicate;
    }
    //还可以设置排序 从小到大 或者从大到小
    //按照年龄降序 的一个描述
    NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
    //按照 name 进行 升序排列
    NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
#if 0
    request.sortDescriptors = @[sort1];//按照一个准则排序 age
#else
    //先按照 age 进行降序排 ,如果出现age 相同 那么 再按照name 升序排序
    request.sortDescriptors = @[sort1,sort2];
#endif
  
    //不设置 谓词 那么找所有
    
    //5.执行 查询请求  返回一个数组
    NSArray *resultArr = [_context executeFetchRequest:request error:nil];
    return resultArr;
}
封装以后直接调就行了
二维码(多关注点github好东西很多的)
第三方库ZBarSDK
导入库
导入系统库
libz.dylib
libicony.dylib
QuartzCore.framework
CoreVideo.framework
CoreMedia.framework
AVfoundation.framwork
原理示例:
二维码编译顺序
Zbar编译
需要添加AVFoundation  CoreMedia  CoreVideo QuartzCore libiconv
ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithBlock:^(NSString *str, BOOL isScceed) {
    if (isScceed) {
    NSLog(@"扫描后的结果~%@",str);
            }
}];
[self presentViewController:vc animated:YES completion:nil];
生成二维码
拖拽libqrencode包进入工程,注意点copy
添加头文件#import "QRCodeGenerator.h"
imageView.image=[QRCodeGenerator qrImageForString:@"这个是什么" imageSize:imageView.bounds.size.width];

#import "ZCZBarViewController.h"
#import "QRCodeGenerator.h"
UIButton*button=[UIButton buttonWithType:UIButtonTypeSystem];
    button.frame=CGRectMake(0, 70, 100, 100);
    [button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"扫描二维码" forState:UIControlStateNormal];
    [self.view addSubview:button];
UIImageView*imageview=[[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 200, 200)];
    imageview.image=[QRCodeGenerator qrImageForString:@"生成二维码" imageSize:300];
    [self.view addSubview:imageview];
-(void)btn:(UIButton*)button
{

ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithBlock:^(NSString *str, BOOL isScceed) {
        if (isScceed) {
            NSLog(@"扫描后的结果~%@",str);
        }
    }];
    [self presentViewController:vc animated:YES completion:nil];
}
推送
本地推送,网络推送,激光推送(要钱呀!屌丝伤不起)
网络推送:
应用场景
提醒业务,比如一些秀场,女主播可以通知他们的土豪(比如我),赶紧来撒钱
每天晚上8点影视剧的推送
小说更新
游戏活动推送等
//在这个方法里面写
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[[UIDevice currentDevice]systemVersion]floatValue]>=8.0) {
        [[UIApplication sharedApplication]registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeSound|UIUserNotificationTypeBadge) categories:nil]];
        //开启通知
        [[UIApplication sharedApplication]registerForRemoteNotifications];
    }

}
//当我们接到通知之后,如何去处理,首先去处理一个标识
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
//我们首先获取一个token值,相当于我们用的QQ,需要一个QQ号码,那么这个QQ是谁,是苹果服务器,我们自己通过自己的设备向苹果服务器发送一个请求,告诉他们我们应用的一个标示,作为他们的联系
    //获取token需要进行处理,把这个标示发给我们服务器端做记录,当我们的服务器需要给用户发消息的时候,使用这个标示符+我们要发送的消息给苹果服务器,拼过会根据这个标示符发到对应的手机的里面
    //因为在有网的情况下,手机是一直和苹果服务器保持者联系,从理论上来说苹果可以控制任何一台手机的情况下进行相关的操作
    //最明显的就是,在有网的情况下,你收不到任何消息,但是在有网的情况下会弹出很多消息
NSLog(@"%@",deviceToken );
}
//出错处理
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"%@",error);
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    //接受推到消息的是一个字典,是规定的格式
    
}
本地推送:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    }
   /创建一个本地推送
    UILocalNotification*local=[[UILocalNotification alloc]init];
    //设置推送内容
    local.alertBody=@“亲,什么时候约;
    //设置声音
    local.soundName=@"au_gameover.wav";
   //设置推送数目
    local.applicationIconBadgeNumber=1000;
    local.fireDate=[NSDate  dateWithTimeIntervalSinceNow:10];
    //把推送任务增加到推送队列中,需要注意,推送通知后,程序就算被杀掉,推送通知任然可以运行
//虚拟机上如果要看效果的话
//如果要弹出推送通知,需要程序退出后台,快捷键Connand+Shitf+h
    [[UIApplication sharedApplication]scheduleLocalNotification:local];
/*
  //删除通知
    NSArray*localArray=[UIApplication sharedApplication].scheduledLocalNotifications;
    //遍历通知
    for (UILocalNotification* notification in localArray) {
        if ([notification.alertBody isEqual:@"亲,什么时候约"]) {
            [[UIApplication sharedApplication]cancelLocalNotification:notification];
        }
    }
   //删除所有的通知
   // [[UIApplication sharedApplication]cancelAllLocalNotifications];
/*
     本地推送的加入方式,比如判断。3天没来,每次程序启动,把原来的旧通知,并且计算出3天后的时间
    
    */
//    NSInteger num=[UIApplication sharedApplication].applicationIconBadgeNumber;
//    num=num+1;
//    local.applicationIconBadgeNumber=num;
*/

}
//激光有Demo
VLC(网上有教程)
VLC集成指南
添加libMobileVLCKit
添加库
libstdc++
libiconv
libbz2
Security
QuartzCore
CoreText
CFnetWork
OpenGLES
AudioToolbox
修改C++编译器为stdC++

聊天(tcp-udp)

(socket库)
#import "AsyncSocket.h"
协议
AsyncSocketDelegate
//建立发送端
    AsyncSocket * sendSocket;
    //建立服务端
    AsyncSocket * severSocket;
//建立一个数组保存连接
@property(nonatomic,strong)NSMutableArray * socketArray;

/*
       建立一个群聊,学生向教师端发送消息,教师端显示所有消息
     */
    
   - (void)CreatSocket
{
    sendSocket=[[AsyncSocket alloc] initWithDelegate:self];
    severSocket=[[AsyncSocket alloc] initWithDelegate:self];
    //服务端绑定端口,监听该端口接收的数据
    /*
       端口最大为65535,其中建议设置为5000以上,另外还有一些特殊的端口,例如8080为视频端口,建议不要占用
     */
    [severSocket acceptOnPort:5678 error:nil];
    
    
}
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
  //接收的一个新连接,这个连接需要保存一下,然后持续保持连接
    [self.socketArray addObject:newSocket];
    
    //其中-1标示持续观察,如果设置为300,那么300秒以后就不在观察
    [newSocket readDataWithTimeout:-1 tag:100];
    
    
}
//协议方法
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
   //接收到的数据
    NSString * message=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if (_textView) {
        //在原来的旧数据上面,追加新的数据
        _textView.text=[NSString stringWithFormat:@"%@%@",_textView.text,message];
    }
    
    [sock readDataWithTimeout:-1 tag:100];
    
}

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
//发送成功
}
//textfild协议
//发送数据
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
    if (textField.text.length>0) {
        // 发送数据
        if (![sendSocket isConnected]) {
            //确定是否连接,如果没有连接,则开始连接host:后面是iP地址
            [sendSocket connectToHost:@"192.168.2.7" onPort:5678 error:nil];
        }
        //当连接完成以后,发送数据
        //拼接数据是谁说,我希望获得当前设备的名称
       // [[UIDevice currentDevice]systemName];该方法只有在真机上才有效,在模拟器上无效
        NSString * message=[NSString stringWithFormat:@"%@说:%@\n",@"房骞",textField.text];
        [sendSocket writeData:[message dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:100];
  
    }
    return YES;
}
屏幕截图
ZCScreenShot库

此类用于屏幕截图
添加库:无
代码示例 为截取全屏
[BeginImageContext beginImageContext:self.view.frame View:self.view];
2个参数 第一个参数用于截取的范围,第二个参数截取哪个view上

//示例代码
[ZCScreenShot beginImageContext:self.view.frame View:self.view];
//第一个参数是截取图片的范围,第二个参数是截取的那一层
#import "ZCScreenShot.h"
    UIImage *image=[ZCScreenShot beginImageContext:self.view.frame View:self.view];
(上面两个加起来就是一个小型教学客户端呀)

语音
(科大讯飞)
讯飞官方demo吧,实在是太全了我就不献丑了
阅读更多
文章标签: ios
个人分类: iOS开发
上一篇Cocoapos: The dependency `AFNetworking ` is not used in any concrete target
下一篇could not find developer disk image解决方法
想对作者说点什么? 我来说一句

spring一些常用知识点

2010年12月22日 14KB 下载

qt各大知识点的小实例汇总

2013年11月11日 3.02MB 下载

bootstrap的资料

2017年12月21日 741KB 下载

Java多线程

2016年03月01日 930KB 下载

UE4 C++编程常用知识点总结

2018年07月12日 18KB 下载

HTML学习文档及总结

2009年05月31日 133KB 下载

一些常用积分的基本公式

2009年10月08日 150KB 下载

常用一些jar包

2016年08月17日 19.42MB 下载

数据结构的重要知识点归纳

2012年02月14日 558KB 下载

jquery标签切换知识点总结源码

2015年10月02日 123KB 下载

没有更多推荐了,返回首页

关闭
关闭