项目功能大全,让你的项目一天搞定
今天有人问我如何开始写一个项目,不禁回忆起自己写第一个项目的时候,到现在,突然感觉自己写的好多都是在重复,有些感想,特此写下这篇文章,给想入这行的新手们一些参考
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];//按照一个准则排序 ageelse //先按照 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];
上面两个加起来就是一个小型教学客户端呀
转载于:https://www.cnblogs.com/xjy-123/p/5162995.html
项目功能大全,让你的项目一天搞定相关推荐
- 【2022 CCF BDCI 文心大模型创意项目】中秋款文心带你轻松搞定MV制作
[2022 CCF BDCI 文心大模型创意项目]中秋款文心带你轻松搞定MV制作 项目效果先知 项目地址: https://aistudio.baidu.com/aistudio/projectdet ...
- 不懂技术的项目经理,学会这2点就能搞定项目!
"不懂技术"一直是一类项目经理最大的痛楚. 我之前还特意写过一篇关于项目经理要不要懂技术的文章. 里面的观点很明确:不懂技术的PM,最终会尝尽生活的苦. 项目经理到底要不要懂技术? ...
- 图片提取文字功能很神奇?Java几行代码搞定它!
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/weixin_44671737/ article/details/110000864 摘要 近日浏 ...
- 图片提取文字功能很神奇?Java几行代码搞定它
摘要 近日浏览网上一些图片提取文字的网站,觉得甚是有趣,花费半日也做了个在线图片识别程序,完成了两个技术方案的选择,一是tesseract+python flask的方案实现,二是tesseract+ ...
- Photoshop CC重磅功能发布:复杂抠图也能一键搞定
近日,Adobe正式推出了Photoshop CC 19. 1 版本,去年 11 月份曾预告过的"选取对象"功能正式上线,不管是人物.动物.车辆.玩具--只需一个按钮,就能快速选取 ...
- 支付宝上线新功能:去这个国家入境十分钟搞定!
11月15日,作为"新马泰"旅游胜地的泰国是出国旅游热度最高的几个国家之一.据统计,2018年中国游客赴泰旅游突破了1054万人,比2017年上升了7.4%.2018年赴泰旅游的中 ...
- Qt框架类图大全,类继承关系一图搞定
一张图搞定所有Qt类,点击进入可查看各个类的详细信息. 新手最合适哦. Qt类详细
- android个人支付功能,个人app支付接入(三分钟搞定个人微信支付,支付宝支付问题)---贝贝支付...
前言 想必很多人个人开发者和我有同样的感触,想要在自己开发的app中接入微信支付和支付宝支付,仅仅是去申请支付接口就把我们挡在了门外,微信和支付宝都只对接企业的,那不是想逼死我们个人开发者吗?一开始使 ...
- android开源项目框架大全:《IT蓝豹》
2019独角兽企业重金招聘Python工程师标准>>> android开源项目框架大全: 1.多页切换TabHost 9 android-sticky-viewpager ViewP ...
最新文章
- AI一分钟 | “芯片门”影响仍在,英伟达旗下多款芯片也遭遇“幽灵”漏洞影响;贾跃亭邀媒体试乘法乐第FF91,你怎么看?
- Apache Maven 2 简介
- PAT甲级1071 Speech Patterns :[C++题解]字符串哈希
- linux下执行shell脚本文件,Linux下使用shell脚本自动执行脚本文件
- SAP Fiori Elements save按钮的实现细节
- python使用工具简介介绍
- ROS入门 SLAM
- virt-install选项详解
- Java POI 导出EXCEL经典实现 Java导出Excel弹出下载框(转载)
- 倒车雷达matlab仿真,倒车雷达系统设计(超声波-SEG4)
- Java中Object转化为int类型
- 小米笔记本备份、SSD分区、U盘Ghost详解及对产品的建议
- OPNsense用户手册中文版
- python元类 orm_Python3 元类与ORM
- android屏幕亮度自动调节解析
- 【技美百人计划】图形 4.4 抗锯齿概论
- D41FCB31FC1NE70 派克比例阀
- java工具类获取文件扩展名与content-type、http与content-type映射关系
- linux4.1内核配置以及编译及千兆网卡dp83867网卡驱动移植
- 刀片式服务器与虚拟机,为什么人们在开发虚拟主机时更喜欢刀片服务器?
热门文章
- 最新MyEclipseIDEAWebStorm安装 激活
- 那年学过的Web前端笔记
- 那年学过的Oracle笔记
- 台式计算机的主流配置,2017年台式电脑主流配置单
- xampp安装后无法启动apache
- list(链表)容器
- excel服务器没有响应怎么办,勤哲Excel服务器技术支持|Excel服务器常见问题解答...
- mysql的设计模式_数据库设计中使用设计模式
- 扫描服务器用户,服务器安全工具(自动扫描后门路径)
- android post数据到php服务器,通过post方法将数据上传到服务器Android Studio