• 项目功能大全,让你的项目一天搞定


    今天有人问我如何开始写一个项目,不禁回忆起自己写第一个项目的时候,到现在,突然感觉自己写的好多都是在重复,有些感想,特此写下这篇文章,给想入这行的新手们一些参考

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

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

    废话不说了直接开写程序
    很重要(1)首先我们要确定明确开发需要的框架,一个好的框架可以让我们轻松很多

    框架可以自己写,也可以从网上找,多对比一下会有惊喜的
    页面
    (1)一般每个详情页面都有相应的导航栏;如果有直接参考(见导航Deno,直接输入图片网址或者本地图片,设置坐标一键搞定);如果没有直接跳过
    (2)然后就到了图文布局了:(推荐xib或storyboard)强大快速(尤其项目比较急的时候更是不二选择);不熟练的话那就老实的算坐标,布局吧!这个情况太多,一般难度也不大,费点心基本都可以搞定(我在这里就不详细说了。)
    我这里就按功能说了(不需要就直接跳过)

    功能:搜索

    第一种搜索:UISearchBar 遵守协议
    //将要进入编辑模式调用

    • (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
      //显示cancel 按钮
      [searchBar setShowsCancelButton:YES animated:YES];
      return YES;
      }


    //将要退出编辑模式调用

    • 1 (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
      2 请把代码粘贴在这里
      3 //隐藏cancel 按钮
      4 [searchBar setShowsCancelButton:NO animated:YES];
      5 return YES;
      6 }

    // 点击 搜索按钮的时候调用

    •  1 (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { 2 //写入搜索内容(根据需要进行搜索) 3 } 

    //点击cancel 被调用

    • 1 (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
      2 //清空内容
      3 searchBar.text = @"";
      4 [searchBar resignFirstResponder];//收键盘
      5 }
    • 第二种搜索

    • 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]; NSStringcaches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
      NSStringmycacehs=[caches stringByAppendingPathComponent:@"MyCaches"];
      NSDirectoryEnumeratorenumor=[[NSFileManager defaultManager]enumeratorAtPath:mycacehs];
      NSUInteger mysize=0;
      for (NSString filename in enumor) {
      NSStringfilepath=[mycacehs stringByAppendingPathComponent:filename];
      NSDictionaryfiledict=[[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.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
      {
      NSStringsql=@"update user name=? where num<50 ";
      if ([_database executeUpdate:sql,@"小红" ]) {
      NSLog(@"updata error:%@",_database.lastErrorMessage);
      }
      }
      //删除数据
      -(void)deletedatawithNUm:(NSInteger)num
      {
      NSStringsql=@"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
      ZCZBarViewControllervc=[[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"
      UIButtonbutton=[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];
      UIImageViewimageview=[[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 200, 200)];
      imageview.image=[QRCodeGenerator qrImageForString:@"生成二维码" imageSize:300];
      [self.view addSubview:imageview];
      -(void)btn:(UIButton*)button
      {
      
      ZCZBarViewControllervc=[[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]];
      }
      /创建一个本地推送
      UILocalNotificationlocal=[[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];
      /
      //删除通知
      NSArraylocalArray=[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:@"%@说:%@
      ",@"房骞",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];

    上面两个加起来就是一个小型教学客户端呀 

  • 相关阅读:
    时间复杂度,空间复杂度
    冒泡排序,选择排序,插入排序
    redis集群
    redis进阶
    redis常识--基础
    mysql基本操作
    TCP/IP 的介绍
    OSI七层网络模型&TCP&UDP&三握四挥
    DNS
    局域网&广域网
  • 原文地址:https://www.cnblogs.com/xjy-123/p/5162995.html
Copyright © 2020-2023  润新知