今天有人問我如何開始寫一個項目,不由回憶起本身寫第一個項目的時候,到如今,忽然感受本身寫的好多都是在重複,有些感想,特此寫下這篇文章,給想入這行的新手們一些參考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];
上面兩個加起來就是一個小型教學客戶端呀