今天有人问我如何开始写一个项目,不由回忆起本身写第一个项目的时候,到如今,忽然感受本身写的好多都是在重复,有些感想,特此写下这篇文章,给想入这行的新手们一些参考git
1.写项目以前首先咱们要肯定需求,明确项目须要实现哪些功能(吐槽下:好多项目的大部分功能都是同样的)github
2,美工,后台啥的我都直不一一说了状况都不同sql
废话不说了直接开写程序
很重要(1)首先咱们要肯定明确开发须要的框架,一个好的框架可让咱们轻松不少数据库
框架能够本身写,也能够从网上找,多对比一下会有惊喜的
页面
(1)通常每一个详情页面都有相应的导航栏;若是有直接参考(见导航Deno,直接输入图片网址或者本地图片,设置坐标一键搞定);若是没有直接跳过
(2)而后就到了图文布局了:(推荐xib或storyboard)强大快速(尤为项目比较急的时候更是不二选择);不熟练的话那就老实的算坐标,布局吧!这个状况太多,通常难度也不大,费点心基本均可以搞定(我在这里就不详细说了。)
我这里就按功能说了(不须要就直接跳过)json
功能:搜索数组
第一种搜索: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 }
// 点击 搜索按钮的时候调用微信
//点击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:@"%@说:%@\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];
上面两个加起来就是一个小型教学客户端呀