真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ios開發(fā)實例教程,ios程序設(shè)計及實踐

如何快速的開發(fā)一個完整的iOS直播App

首先從main.m文件的main函數(shù)開始執(zhí)行的。

創(chuàng)新互聯(lián)建站長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為青海企業(yè)提供專業(yè)的成都網(wǎng)站設(shè)計、成都網(wǎng)站制作,青海網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

int main(int argc, char * argv[])

{

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

//1、principalClassName:應(yīng)用程序?qū)ο蟮念惷║IApplication或其子類)

//2、delegateClassName:應(yīng)用程序delegate的類名。(任何接受了UIApplicationDelegate的類)

UIApplicationMain根據(jù)上述兩個類名創(chuàng)建應(yīng)用程序?qū)嵗?、?yīng)用程序代理實例。然后建立事件循環(huán)(runloop),檢測程序的各種事件(程序開始啟動,接收到觸摸等等)

在執(zhí)行UIApplicationMain函數(shù)時做了跳轉(zhuǎn),轉(zhuǎn)到了AppDelete中。應(yīng)用程序代理,主要檢測應(yīng)用程序的狀態(tài)并做出相應(yīng)的處理。應(yīng)用程序的狀態(tài)有很多,比如:程序啟動、進入活躍狀態(tài)、進到后臺、內(nèi)存警告、收到遠程消息等等。任何接受了UIApplicationDelegate協(xié)議的對象都可以成為應(yīng)用程序代理。一旦應(yīng)用程序的某種狀態(tài)觸發(fā),就會執(zhí)行相應(yīng)的代理方法。UIApplicationDelegate是一個OC的協(xié)議。里面聲明了一堆方法,這些方法都與應(yīng)用程序運行狀態(tài)有關(guān),它們由應(yīng)用程序代理實現(xiàn)。UIApplication對象負責調(diào)用。

application:didFinishLaunchingWithOptions:告訴delegate程序啟動即將完成,程序準備要運行。(delegate實現(xiàn)這個方法時,要創(chuàng)建window對象,將程序內(nèi)容通過window呈現(xiàn)給用戶。),在該方法中為我們應(yīng)用程序創(chuàng)建window等必要的界面

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

怎么在ios開發(fā)中使用opengl

一、搭建開發(fā)環(huán)境

1. 打開Xcode, 新建一個工程

選擇:IOS - Application - Single View Application模板

輸入工程名稱和基本信息,勾選“UseStoryboards”,然后創(chuàng)建

2. 添加必要的框架

在“Build Phases”中,添加三個框架

3. 修改viewController。h

添加 “#import”,并將它修改為繼承"GLKViewController"

4. 修改“view”的類

雙擊“MainStoryboard.storyboard”展開,選擇"view"

然后,在“Identity Inspector"中,將它的類改為”GLKView“

好了,OpenGL的環(huán)境基本上搭建出來了。

二、增加自己代碼

基本上,所有的代碼都是加到ViewController.m文件中

1、添加全局屬性聲明

@interface ViewController ()@property(strong,nonatomic)EAGLContext*

context;@property(strong,nonatomic)GLKBaseEffect* effect;@end@implementation

ViewController@synthesize context, effect;

2、 添加一組頂點數(shù)據(jù)

這是一個正方形頂點數(shù)組。實際上它是二個三角形接合而成的

GLfloat squareVertexData[48] ={ 0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f,

1.0f, -0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f,

0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,

-0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.9f, 0.0f,

0.0f, 1.0f, 1.0f, 1.0f,};

每行頂點數(shù)據(jù)的排列含義是:

頂點X、頂點Y,頂點Z、法線X、法線Y、法線Z、紋理S、紋理T。

在后面解析此數(shù)組時,將參考此規(guī)則。

頂點位置用于確定在什么地方顯示,法線用于光照模型計算,紋理則用在貼圖中。

一般約定為“頂點以逆時針次序出現(xiàn)在屏幕上的面”為“正面”。

世界坐標是OpenGL中用來描述場景的坐標,Z+軸垂直屏幕向外,X+從左到右,Y+軸從下到上,是右手笛卡爾坐標系統(tǒng)。我們用這個坐標系來描述物體及光源的位置。

三、初始化OpenGL環(huán)境

1、 基本的初始化代碼

在ViewController.m中有個函數(shù)(void)viewDidLoad,它是程序運行時,初始化回調(diào)函數(shù)。在viewDidLoad函數(shù)內(nèi)補充我們自己的初始化代碼。

// 使用“ES2”創(chuàng)建一個“EAGLEContext”實例 self.context = [[[EAGLContext

alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2]autorelease]; //

將“view”的context設(shè)置為這個“EAGLContext”實例的引用。并且設(shè)置顏色格式和深度格式。 GLKView* view =

(GLKView*)self.view; view.context = self.context; view.drawableColorFormat =

GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat =

GLKViewDrawableDepthFormat24; //

將此“EAGLContext”實例設(shè)置為OpenGL的“當前激活”的“Context”。這樣,以后所有“GL”的指令均作用在這個“Context”上。隨后,發(fā)送第一個“GL”指令:激活“深度檢測”。

[EAGLContext setCurrentContext:context]; glEnable(GL_DEPTH_TEST); //

創(chuàng)建一個GLK內(nèi)置的“著色效果”,并給它提供一個光源,光的顏色為綠色。 self.effect = [[[GLKBaseEffect

alloc]init]autorelease]; self.effect.light0.enabled = GL_TRUE;

self.effect.light0.diffuseColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);

2、 運行?,F(xiàn)在應(yīng)該是粉紅色屏幕了(目前場景仍是空的),說明初始化過程沒問題

四、 將項點數(shù)據(jù)寫入能用的頂點屬性存儲區(qū)

1、 寫入過程

首先將數(shù)據(jù)保存進GUP的一個緩沖區(qū)中,然后再按一定規(guī)則,將數(shù)據(jù)取出,復(fù)制到各個通用頂點屬性中。

注:如果頂點數(shù)據(jù)只有一種類型(如單純的位置坐標),換言之,在讀數(shù)據(jù)時,不需要確定第一個數(shù)據(jù)的內(nèi)存位置(總是從0開始),則不必事先保存進緩沖區(qū)。

2、 頂點數(shù)組保存進緩沖區(qū)

//

聲明一個緩沖區(qū)的標識(GLuint類型)讓OpenGL自動分配一個緩沖區(qū)并且返回這個標識的值.綁定這個緩沖區(qū)到當前“Context”.最后,將我們前面預(yù)先定義的頂點數(shù)據(jù)“squareVertexData”復(fù)制進這個緩沖區(qū)中。

// 注:參數(shù)“GL_STATIC_DRAW”,它表示此緩沖區(qū)內(nèi)容只能被修改一次,但可以無限次讀取。 GLuint buffer;

glGenBuffers(1, buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);

glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData,

GL_STATIC_DRAW);

3、將緩沖區(qū)的數(shù)據(jù)復(fù)制進能用頂點屬性中

glEnableVertexAttribArray(GLKVertexAttribPosition);

glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 4*8,

(char*)NULL + 0);

首先,激活頂點屬性(默認它的關(guān)閉的)?!癎LKVertexAttribPosition”是頂點屬性集中“位置Position”屬性的索引。

頂點屬性集中包含五種屬性:位置、法線、顏色、紋理0,紋理1。

它們的索引值是0到4。

激活后,接下來使用“glVertexAttribPointer”方法填充數(shù)據(jù)。

iOS 開發(fā) delegate詳解

首先,讓我們看看為什么要使用delegate。

一個典型的ios應(yīng)用程序會有各種類型的對象:windows,tables,buttons,input boxes等等。在一個特定的應(yīng)用程序中,你會讓每個對象做特定的事情。比如說當用戶點擊一個按鈕的時候,會執(zhí)行一個特定的操作或者使用一個table顯示特定的數(shù)據(jù)。

每個對象實例會有處理 特定 的事情。比如說我們有一個UITableView的實例,我們可能會讓它以特定的方式來顯示特定的 數(shù)據(jù),同樣的,我們對table的每一行進行tapping或者swiping操作的時候,它們也會做出自己特有的事件處理方式。為了避免為達到某一個特定的目的(actions or events)而創(chuàng)建一個子類(如果有多種不同的特定目的就會創(chuàng)建多個子類),你可以寫出響應(yīng)這些操作或者事件的方法,它們會在這些操作或者事件發(fā)生的時候被調(diào)用,為了達到此目的,你只需要給這個對象一個delegate(一個對象)。你可以使一個類作為其他一個對象或者多個對象的delegate。

簡單的說代理就是在類外,讓特定的人對該類做特定的操作的一種實現(xiàn)方法。

iOS開發(fā)中遇到的小問題-----總結(jié)

1、統(tǒng)一收鍵盤的方法

[[[UIApplication sharedApplication] keyWindow] endEditing:YES];

2、提示框

BBAlertView *alert = [[BBAlertView alloc] initWithStyle:BBAlertViewStyleDefault

Title:@"刪除訂單"

message:@"是否刪除訂單,"

customView:nil

delegate:self

cancelButtonTitle:L(@"取消")

otherButtonTitles:L(@"確認")];

[alert setCancelBlock:^{

}];

[alert setConfirmBlock:^{

[self orderDidRemovePressDown:tempDic Index:index.section];

}];

[alert show];

3、圖片的自適應(yīng)功能

self.brandImage.contentMode = UIViewContentModeScaleAspectFit;

4、cocoaPods清除緩存問題

$ sudo rm -fr ~/.cocoapods/repos/master

$ pod setup

5、設(shè)置顯示鍵盤的樣式

textView.keyboardType =UIKeyboardTypeDefault;

//設(shè)置鍵盤右下角為完成(中文輸入法下)

textView.returnKeyType=UIReturnKeyDone;

6、輸出當前時間

NSDateFormatter * dateFormatter=[[NSDateFormatter alloc]init];

[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];

NSLog(@"當前毫秒時間1==%@",[dateFormatter stringFromDate:[NSDate date]]);

7、顯示兩秒然后消失

UILabel * lab=[[UILabel alloc]initWithFrame:CGRectMake(60,Main_Screen_Height-64-49-60, Main_Screen_Width-120, 50)];

lab.backgroundColor=[UIColor grayColor];

ViewRadius(lab, 20);

lab.textAlignment=NSTextAlignmentCenter;

lab.text=@"請先進行實名制驗證";

[self.view addSubview:lab];

[UILabel animateWithDuration:2 animations:^{

lab.alpha=0;

}completion:^(BOOL finished) {

[lab removeFromSuperview];

}];

8、設(shè)置placeholder屬性的大小和顏色

[_phoneFie setValue:[UIColor grayColor] forKeyPath:@"_placeholderLabel.textColor"];

[_phoneFie setValue:[UIFont boldSystemFontOfSize:15] forKeyPath:@"_placeholderLabel.font"];

_phoneFie.returnKeyType=UIReturnKeyDone;

9、設(shè)置cell的交互完全不可以使用

//[cellTwo setUserInteractionEnabled:NO];

//設(shè)置cell不可以點擊,但是上面的子控件可以交互

cellTwo.selectionStyle=UITableViewCellSelectionStyleNone;

10、將textField的placeholder 屬性的字體向右邊移動5

_field.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10*Width_375, _field.frame.size.height)];

_field.leftViewMode = UITextFieldViewModeAlways;

11、開新線程使按鈕上的時間變化

-(void)startTime{

__block int timeout=60; //倒計時時間

UIButton * btn=(UIButton *)[self.view viewWithTag:1000];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);

dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒執(zhí)行

dispatch_source_set_event_handler(_timer, ^{

if(timeout=0){

dispatch_source_cancel(_timer);

dispatch_async(dispatch_get_main_queue(), ^{

[btn setTitle:@"發(fā)送驗證碼" forState:UIControlStateNormal];

btn.enabled = YES;

});

}else{

//? int minutes = timeout / 60;

int miao = timeout % 60;

if (miao==0) {

miao = 60;

}

NSString *strTime = [NSString stringWithFormat:@"%.2d", miao];

dispatch_async(dispatch_get_main_queue(), ^{

[btn setTitle:[NSString stringWithFormat:@"剩余%@秒",strTime] forState:UIControlStateNormal];

btn.enabled = NO;

});

timeout--;

}

});

dispatch_resume(_timer);

}

12、隱藏TableView 中多余的行

UIView * view=[[UIView alloc]initWithFrame:CGRectZero];

[_tabelView setTableFooterView:view];

13、UIView添加背景圖片

UIImage * image=[UIImage imageNamed:@"friend750"];

headSeV.layer.contents=(id)image.CGImage;

14、UITableView取消選中狀態(tài)

[tableView deselectRowAtIndexPath:indexPath animated:YES];// 取消選中

15、帶屬性的字符串

NSFontAttributeName? 字體

NSParagraphStyleAttributeName? 段落格式

NSForegroundColorAttributeName? 字體顏色

NSBackgroundColorAttributeName? 背景顏色

NSStrikethroughStyleAttributeName 刪除線格式

NSUnderlineStyleAttributeName? ? ? 下劃線格式

NSStrokeColorAttributeName? ? ? ? 刪除線顏色

NSStrokeWidthAttributeName 刪除線寬度

NSShadowAttributeName? 陰影

1.? 使用實例

UILabel *testLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 320, 30)];

testLabel.backgroundColor = [UIColor lightGrayColor];

testLabel.textAlignment = NSTextAlignmentCenter;

NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:@"今天天氣不錯呀"];

[AttributedStr addAttribute:NSFontAttributeName

value:[UIFont systemFontOfSize:16.0]

range:NSMakeRange(2, 2)];

[AttributedStr addAttribute:NSForegroundColorAttributeName

value:[UIColor redColor]

range:NSMakeRange(2, 2)];

testLabel.attributedText = AttributedStr;

[self.view addSubview:testLabel];

16、加大按鈕的點擊范圍

把UIButton的frame 設(shè)置的大一些,然后給UIButton設(shè)置一個小些的圖片

[tmpBtn setImageEdgeInsets:UIEdgeInsetsMake(5, 5, 5, 5)];

// 注意這里不能用setBackgroundImage

[tmpBtn setImage:[UIImage imageNamed:@"testBtnImage"] forState:UIControlStateNormal];

17、//避免self的強引用

__weak ViewController *weakSelf = self;

18、//類別的創(chuàng)建

command +n ——Objective-C File———(File Type? 選擇是類別還是擴展)———(Class? 選擇為哪個控件寫類別)

19、修改UITableview 滾動條顏色的方法

self.tableView.indicatorStyle=UIScrollViewIndicatorStyleWhite;

20、利用UIWebView顯示pdf文件

webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];

[webView setDelegate:self];

[webView setScalesPageToFit:YES];

[webViewsetAutoresizingMask:UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight];

[webView setAllowsInlineMediaPlayback:YES];

[self.view addSubview:webView];

NSString *pdfPath = [[NSBundle mainBundle]pathForResource:@"ojc" ofType:@"pdf"];

NSURL *url = [NSURLfileURLWithPath:pdfPath];

NSURLRequest *request = [NSURLRequestrequestWithURL:url

cachePolicy:NSURLRequestUseProtocolCachePolicy

timeoutInterval:5];

[webView loadRequest:request];

21、將plist文件中的數(shù)據(jù)賦給數(shù)組

NSString *thePath = [[NSBundle mainBundle]pathForResource:@"States" ofType:@"plist"];

NSArray *array = [NSArrayarrayWithContentsOfFile:thePath];

22、隱藏狀態(tài)欄

[[UIApplication shareApplication]setStatusBarHidden: YES animated:NO];

23、給navigation? Bar? 設(shè)置title顏色

UIColor *whiteColor = [UIColor whiteColor];

NSDictionary *dic = [NSDictionary dictionaryWithObject:whiteColor forKey:NSForegroundColorAttributeName];

[self.navigationController.navigationBar setTitleTextAttributes:dic];

24、使用AirDrop 進行分享

NSArray *array = @[@"test1", @"test2"];

UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:array applicationActivities:nil];

[self presentViewController:activityVC animated:YES

completion:^{

NSLog(@"Air");

}];

25、把tableview里面Cell的小對勾的顏色改成別的顏色

_mTableView.tintColor = [UIColor redColor];

26、UITableView去掉分割線

_tableView.separatorStyle = NO;

27、正則判斷手機號碼地址格式

- (BOOL)isMobileNumber:(NSString *)mobileNum {

//? ? 電信號段:133/153/180/181/189/177

//? ? 聯(lián)通號段:130/131/132/155/156/185/186/145/176

//? ? 移動號段:134/135/136/137/138/139/150/151/152/157/158/159/182/183/184/187/188/147/178

//? ? 虛擬運營商:170

NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|7[06-8])\\d{8}$";

NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];

return [regextestmobile evaluateWithObject:mobileNum];

}

28、控制交易密碼位數(shù)

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

if (textField.text.length =6){

[MBProgressHUD showMessage:@"密碼為6位" afterDelay:1.8];

return NO;

}

return YES;

}

29、判斷是不是空

if ([real_name isKindOfClass:[NSNull class]] ) {

return NO;}

30、點擊號碼撥打電話

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://400966220"]];

31、控制UITabbar的選擇哪一個

[self.tabBarController setSelectedIndex:1];

32、獲取當前App的版本號

NSDictionary?*infoDictionary?=?[[NSBundle?mainBundle]?infoDictionary];

CFShow(infoDictionary);

//?app名稱

NSString?*app_Name?=?[infoDictionary?objectForKey:@"CFBundleDisplayName"];

//?app版本

NSString?*app_Version?=?[infoDictionary?objectForKey:@"CFBundleShortVersionString"];

//?app?build版本

NSString?*app_build?=?[infoDictionary?objectForKey:@"CFBundleVersion"];

33、蘋果app權(quán)限NSPhotoLibraryUsageDescriptionApp需要您的同意,才能訪問相冊NSCameraUsageDescriptionApp需要您的同意,才能訪問相機NSMicrophoneUsageDescriptionApp需要您的同意,才能訪問麥克風NSLocationUsageDescriptionApp需要您的同意,才能訪問位置NSLocationWhenInUseUsageDescriptionApp需要您的同意,才能在使用期間訪問位置NSLocationAlwaysUsageDescriptionApp需要您的同意,才能始終訪問位置NSCalendarsUsageDescriptionApp需要您的同意,才能訪問日歷NSRemindersUsageDescriptionApp需要您的同意,才能訪問提醒事項NSMotionUsageDescriptionApp需要您的同意,才能訪問運動與健身NSHealthUpdateUsageDescriptionApp需要您的同意,才能訪問健康更新NSHealthShareUsageDescriptionApp需要您的同意,才能訪問健康分享NSBluetoothPeripheralUsageDescriptionApp需要您的同意,才能訪問藍牙NSAppleMusicUsageDescriptionApp需要您的同意,才能訪問媒體資料庫

34、控件設(shè)置邊框

_describText.layer.borderColor = [[UIColor colorWithRed:215.0 / 255.0 green:215.0 / 255.0 blue:215.0 / 255.0 alpha:1] CGColor];

_describText.layer.borderWidth = 1.0;

_describText.layer.cornerRadius = 4.0;

_describText.clipsToBounds = YES;

35、//隱藏電池條的方法

-(BOOL)prefersStatusBarHidden{

return YES;

}

36、延時操作

[NSThread sleepForTimeInterval:2];

方法二:

[self performSelector:@selector(delayMethod) withObject:nil afterDelay:1.5];

37、系統(tǒng)風火輪:

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO; //隱藏

38、//didSelectRowAtIndexPath:方法里面找到當前的Cell

AssessMentCell * cell = [tableView cellForRowAtIndexPath:indexPath];

39、navigation上返回按鈕的顏色以及返回按鈕后面文字去掉

//返回按鈕后邊文字去掉

[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)

forBarMetrics:UIBarMetricsDefault];

//設(shè)置左上角返回按鈕的顏色

self.navigationController.navigationBar.tintColor = UIColorFromRGB(0x666666);

40、lineBreakMode //設(shè)置文字過長時的顯示格式

label.lineBreakMode = NSLineBreakByCharWrapping;以字符為顯示單位顯

示,后面部分省略不顯示。

label.lineBreakMode = NSLineBreakByClipping;剪切與文本寬度相同的內(nèi)

容長度,后半部分被刪除。

label.lineBreakMode = NSLineBreakByTruncatingHead;前面部分文字

以……方式省略,顯示尾部文字內(nèi)容。

label.lineBreakMode = NSLineBreakByTruncatingMiddle;中間的內(nèi)容

以……方式省略,顯示頭尾的文字內(nèi)容。

label.lineBreakMode = NSLineBreakByTruncatingTail;結(jié)尾部分的內(nèi)容

以……方式省略,顯示頭的文字內(nèi)容。

label.lineBreakMode = NSLineBreakByWordWrapping;以單詞為顯示單位顯

示,后面部分省略不顯示。

iOS藍牙開發(fā):藍牙的連接和數(shù)據(jù)的讀寫

藍牙開發(fā)說簡單也簡單,說不簡單也有點難,開發(fā)人員在首次開發(fā)藍牙前首先需要搞清楚藍牙開發(fā)的概念,還要了解掌握藍牙開發(fā)的一整套流程,這樣才能快速上手開發(fā)藍牙。

? 藍牙開發(fā)分為兩種模式:管理者模式和中心者模式。管理者模式基本很少用到,相當于iPhone手機作為外設(shè),自己創(chuàng)建服務(wù)和特性,然后用其他設(shè)備連接iPhone手機;中心者模式一般是大部分情況下都會使用的,使用中心者模式開發(fā)相當于iPhone手機作為主機,連接藍牙外設(shè),下面介紹藍牙開發(fā)的例子就是使用的中心者模式來講解的。

在這里我還是要推薦下我自己建的iOS開發(fā)學習群:680565220,群里都是學ios開發(fā)的,如果你正在學習ios ,我歡迎你加入,今天分享的這個案例已經(jīng)上傳到群文件,大家都是軟件開發(fā)黨,不定期分享干貨(只有iOS軟件開發(fā)相關(guān)的),包括我自己整理的一份2018最新的iOS進階資料和高級開發(fā)教程

一、關(guān)于藍牙開發(fā)的一些重要的理論概念:

1、服務(wù)(services):藍牙外設(shè)對外廣播的時候一定會有一個服務(wù),有些時候也可以是有多個服務(wù),服務(wù)下面包含一些特性,服務(wù)可以理解成一個模塊的窗口;

2、特征(characteristic):特征存在于服務(wù)下面的,一個服務(wù)下面可以有多個特征,特征可以理解成具體實現(xiàn)功能的窗口,一般的特性都會有value,也就是特征值,是特征和外界交互的最小單位;

? 3、UUID:藍牙上的唯一標示符,為了區(qū)分不同服務(wù)和特征,就用UUID來表示。

二、藍牙連接的主要步驟

?1、創(chuàng)建一個CBCentralManager實例來進行藍牙管理;

?2、搜索掃描外圍設(shè)備;

?3、連接外圍設(shè)備;

?4、獲得外圍設(shè)備的服務(wù);

?5、獲得服務(wù)的特征;

?6、從外圍設(shè)備讀取數(shù)據(jù);

?7、給外圍設(shè)備發(fā)送(寫入)數(shù)據(jù)。

三、藍牙連接和數(shù)據(jù)讀寫的具體步驟

?1、導(dǎo)入蘋果系統(tǒng)藍牙框架

#import

?2、遵循兩個藍牙框架相關(guān)的協(xié)議

3、新建兩個實例屬性,一個特征屬性

@property (nonatomic, strong) CBCentralManager *centralManager; //中心管理者

@property (nonatomic, strong) CBPeripheral *peripheral; //連接到的外設(shè)

@property (nonatomic, strong) CBCharacteristic *characteristic; //特征

?4、初始化CBCentralManager,進行藍牙管理

- (void)viewDidLoad {

[super viewDidLoad];

self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; ? ? //創(chuàng)建實例進行藍牙管理

}

//若中心管理者初始化之后 就會觸發(fā)下面這個代理方法 該代理方法是用來判斷手機藍牙的狀態(tài)的

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {

// 藍牙可用,開始掃描外設(shè)

if (central.state == CBManagerStatePoweredOn) {

NSLog(@"藍牙可用");

//在中心管理者成功開啟之后再進行一些操作

//搜索掃描外設(shè)

// 根據(jù)SERVICE_UUID來掃描外設(shè),如果不設(shè)置SERVICE_UUID,則掃描所有藍牙設(shè)備

// [self.centralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:SERVICE_UUID]]}];

[central scanForPeripheralsWithServices:nil options:nil];

}

if(central.state == CBManagerStateUnsupported) {

NSLog(@"該設(shè)備不支持藍牙");

}

if (central.state == CBManagerStatePoweredOff) {

NSLog(@"藍牙已關(guān)閉");

}

if (central.state == CBManagerStateUnknown) {

NSLog(@"藍牙當前狀態(tài)不明確");

}

if (central.state == CBManagerStateUnauthorized) {

NSLog(@"藍牙未被授權(quán)");

}

}

? 5、搜索外圍設(shè)備

//執(zhí)行掃描動作之后,如果掃描到外設(shè)了,就會自動回調(diào)下面的協(xié)議方法

/** 發(fā)現(xiàn)符合要求的外設(shè),回調(diào) */

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {

NSLog(@"%@====",peripheral.name);

//根據(jù)外設(shè)名字有選擇性的篩選連接藍牙設(shè)備

if ([peripheral.name hasPrefix:@"TEAMOSA"]) {

//在這里對外設(shè)攜帶的廣播數(shù)據(jù)進行進一步的處理

if ([self.peripheraNames containsObject:peripheral.name]) {

//如果數(shù)組中包含了就不再添加

return;

}

//添加到外設(shè)名字數(shù)組中

[self.peripheraNames addObject:peripheral.name];

//標記外設(shè),讓它的生命周期與控制器的一致

self.peripheral = peripheral;

// 可以根據(jù)外設(shè)名字來過濾外設(shè)

// [central connectPeripheral:peripheral options:nil];

}

// 連接外設(shè)

// [central connectPeripheral:peripheral options:nil];

}

6、連接外圍設(shè)備

//連接外圍設(shè)備,中心管理者連接外設(shè)成功,如果連接成功就會回調(diào)這個協(xié)議方法

/** 連接成功 */

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{

//連接成功之后,可以進行服務(wù)和特性的發(fā)現(xiàn)。 停止中心管理設(shè)備的掃描動作,要不然在你和已經(jīng)連接好的外設(shè)進行數(shù)據(jù)溝通時,如果又有一個外設(shè)進行廣播且符合你的連接條件,那么你的iOS設(shè)備也會去連接這個設(shè)備(因為iOS BLE4.0是支持一對多連接的),導(dǎo)致數(shù)據(jù)的混亂。

//停止掃描動作

[self.centralManager stopScan];

// 設(shè)置外設(shè)的代理

peripheral.delegate = self;

// 根據(jù)UUID來尋找服務(wù)

// [peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];

//外設(shè)發(fā)現(xiàn)服務(wù),傳nil代表不過濾,一次性讀出外設(shè)的所有服務(wù)

[peripheral discoverServices:nil];

NSLog(@"%s, line = %d, %@=連接成功", __FUNCTION__, __LINE__, peripheral.name);

}

//外設(shè)連接失敗

/** 連接失敗的回調(diào) */

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

NSLog(@"%s, line = %d, %@=連接失敗", __FUNCTION__, __LINE__, peripheral.name);

}

//丟失連接 掉線

/** 斷開連接 */

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {

NSLog(@"%s, line = %d, %@=斷開連接", __FUNCTION__, __LINE__, peripheral.name);

// 斷開連接可以設(shè)置重新連接

[central connectPeripheral:peripheral options:nil];

}

7、獲取外圍設(shè)備服務(wù)和特征

/** 發(fā)現(xiàn)服務(wù) */

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {

// 遍歷出外設(shè)中所有的服務(wù)

for (CBService *service in peripheral.services) {

// NSLog(@"所有的服務(wù):%@",service);

}

// 這里僅有一個服務(wù),所以直接獲取

CBService *service = peripheral.services.lastObject;

// 根據(jù)UUID尋找服務(wù)中的特征

// [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service];

// [peripheral discoverCharacteristics:@[service.UUID] forService:service];

[peripheral discoverCharacteristics:nil forService:service];

}

8、從外圍設(shè)備讀取數(shù)據(jù)

// 更新特征的value的時候會調(diào)用 (凡是從藍牙傳過來的數(shù)據(jù)都要經(jīng)過這個回調(diào),簡單的說這個方法就是你拿數(shù)據(jù)的唯一方法) 你可以判斷是否 從外圍設(shè)備讀數(shù)據(jù)

/** 接收到數(shù)據(jù)回調(diào) */

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {

// if (characteristic == @"你要的特征的UUID或者是你已經(jīng)找到的特征") {

// //characteristic.value就是你要的數(shù)據(jù)

// }

if ([peripheral.name hasPrefix:@"TEAMOSA"]){

NSData *data = characteristic.value;

NSString *value = [self hexadecimalString:data];

// NSLog(@"characteristic(讀取到的): %@, data : %@, value : %@", characteristic, data, value);

}

// 拿到外設(shè)發(fā)送過來的數(shù)據(jù)

// NSData *data = characteristic.value;

// self.textFild.text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

}

9、向外圍設(shè)備發(fā)送(寫入)數(shù)據(jù)

//這個方法你可以放在button的響應(yīng)里面,也可以在找到特征的時候就寫入,具體看你業(yè)務(wù)需求怎么用

//[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];//第一個參數(shù)是已連接的藍牙設(shè)備; 第二個參數(shù)是要寫入到哪個特征; 第三個參數(shù)是通過此響應(yīng)記錄是否成功寫入 需要注意的是特征的屬性是否支持寫數(shù)據(jù)

/** 寫入數(shù)據(jù)回調(diào) */

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {

/*

typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {

CBCharacteristicPropertyBroadcast = 0x01,

CBCharacteristicPropertyRead = 0x02,

CBCharacteristicPropertyWriteWithoutResponse = 0x04,

CBCharacteristicPropertyWrite = 0x08,

CBCharacteristicPropertyNotify = 0x10,

CBCharacteristicPropertyIndicate = 0x20,

CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,

CBCharacteristicPropertyExtendedProperties = 0x80,

CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,

CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200

};

打印出特征的權(quán)限(characteristic.properties),可以看到有很多種,這是一個NS_OPTIONS的枚舉,可以是多個值

常見的又read,write,noitfy,indicate.知道這幾個基本夠用了,前倆是讀寫權(quán)限,后倆都是通知,倆不同的通知方式

*/

// NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);

// 此時由于枚舉屬性是NS_OPTIONS,所以一個枚舉可能對應(yīng)多個類型,所以判斷不能用 = ,而應(yīng)該用包含

NSLog(@"write value success(寫入成功) : %@", characteristic);

}

10、具體調(diào)用給藍牙外設(shè)寫入數(shù)據(jù)方法,這里的例子是以按鈕點擊事件里面來調(diào)用處理

//發(fā)送按鈕點擊事件

- (void)sendClick {

if (!self.characteristic) {

return;

}

_tempValue = [NSString stringWithFormat:@"%.0f", progressView.centigradeDegree];

_timeValue = [NSString stringWithFormat:@"%.0ld", (long)progressView1.timeDegree];

NSString *ttData = [NSString stringWithFormat:@"%@,%@U", _tempValue, _timeValue];

// NSString *aaa = [DataCoverTool coverFromStringToHexStr:ttData];

// 用NSData類型來寫入

// NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arry];

NSData *data = [ttData dataUsingEncoding:NSUTF8StringEncoding];

// NSData *data = [self dataWithString:ttData];

// 根據(jù)上面的特征self.characteristic來寫入數(shù)據(jù)

[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];


當前名稱:ios開發(fā)實例教程,ios程序設(shè)計及實踐
瀏覽地址:http://weahome.cn/article/dscgjss.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部