ios开发实例教程,ios程序设计及实践-成都创新互联网站建设

关于创新互联

多方位宣传企业产品与服务 突出企业形象

公司简介 公司的服务 荣誉资质 新闻动态 联系我们

ios开发实例教程,ios程序设计及实践

如何快速的开发一个完整的iOS直播App

首先从main.m文件的main函数开始执行的。

创新互联建站长期为千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为青海企业提供专业的成都网站设计、成都网站制作青海网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。

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

{

@autoreleasepool {

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

}

}

//1、principalClassName:应用程序对象的类名(UIApplication或其子类)

//2、delegateClassName:应用程序delegate的类名。(任何接受了UIApplicationDelegate的类)

UIApplicationMain根据上述两个类名创建应用程序实例、应用程序代理实例。然后建立事件循环(runloop),检测程序的各种事件(程序开始启动,接收到触摸等等)

在执行UIApplicationMain函数时做了跳转,转到了AppDelete中。应用程序代理,主要检测应用程序的状态并做出相应的处理。应用程序的状态有很多,比如:程序启动、进入活跃状态、进到后台、内存警告、收到远程消息等等。任何接受了UIApplicationDelegate协议的对象都可以成为应用程序代理。一旦应用程序的某种状态触发,就会执行相应的代理方法。UIApplicationDelegate是一个OC的协议。里面声明了一堆方法,这些方法都与应用程序运行状态有关,它们由应用程序代理实现。UIApplication对象负责调用。

application:didFinishLaunchingWithOptions:告诉delegate程序启动即将完成,程序准备要运行。(delegate实现这个方法时,要创建window对象,将程序内容通过window呈现给用户。),在该方法中为我们应用程序创建window等必要的界面

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

怎么在ios开发中使用opengl

一、搭建开发环境

1. 打开Xcode, 新建一个工程

选择:IOS - Application - Single View Application模板

输入工程名称和基本信息,勾选“UseStoryboards”,然后创建

2. 添加必要的框架

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

3. 修改viewController。h

添加 “#import”,并将它修改为继承"GLKViewController"

4. 修改“view”的类

双击“MainStoryboard.storyboard”展开,选择"view"

然后,在“Identity Inspector"中,将它的类改为”GLKView“

好了,OpenGL的环境基本上搭建出来了。

二、增加自己代码

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

1、添加全局属性声明

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

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

ViewController@synthesize context, effect;

2、 添加一组顶点数据

这是一个正方形顶点数组。实际上它是二个三角形接合而成的

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,};

每行顶点数据的排列含义是:

顶点X、顶点Y,顶点Z、法线X、法线Y、法线Z、纹理S、纹理T。

在后面解析此数组时,将参考此规则。

顶点位置用于确定在什么地方显示,法线用于光照模型计算,纹理则用在贴图中。

一般约定为“顶点以逆时针次序出现在屏幕上的面”为“正面”。

世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。我们用这个坐标系来描述物体及光源的位置。

三、初始化OpenGL环境

1、 基本的初始化代码

在ViewController.m中有个函数(void)viewDidLoad,它是程序运行时,初始化回调函数。在viewDidLoad函数内补充我们自己的初始化代码。

// 使用“ES2”创建一个“EAGLEContext”实例 self.context = [[[EAGLContext

alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2]autorelease]; //

将“view”的context设置为这个“EAGLContext”实例的引用。并且设置颜色格式和深度格式。 GLKView* view =

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

GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat =

GLKViewDrawableDepthFormat24; //

将此“EAGLContext”实例设置为OpenGL的“当前激活”的“Context”。这样,以后所有“GL”的指令均作用在这个“Context”上。随后,发送第一个“GL”指令:激活“深度检测”。

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

创建一个GLK内置的“着色效果”,并给它提供一个光源,光的颜色为绿色。 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、 运行。现在应该是粉红色屏幕了(目前场景仍是空的),说明初始化过程没问题

四、 将项点数据写入能用的顶点属性存储区

1、 写入过程

首先将数据保存进GUP的一个缓冲区中,然后再按一定规则,将数据取出,复制到各个通用顶点属性中。

注:如果顶点数据只有一种类型(如单纯的位置坐标),换言之,在读数据时,不需要确定第一个数据的内存位置(总是从0开始),则不必事先保存进缓冲区。

2、 顶点数组保存进缓冲区

//

声明一个缓冲区的标识(GLuint类型)让OpenGL自动分配一个缓冲区并且返回这个标识的值.绑定这个缓冲区到当前“Context”.最后,将我们前面预先定义的顶点数据“squareVertexData”复制进这个缓冲区中。

// 注:参数“GL_STATIC_DRAW”,它表示此缓冲区内容只能被修改一次,但可以无限次读取。 GLuint buffer;

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

glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData,

GL_STATIC_DRAW);

3、将缓冲区的数据复制进能用顶点属性中

glEnableVertexAttribArray(GLKVertexAttribPosition);

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

(char*)NULL + 0);

首先,激活顶点属性(默认它的关闭的)。“GLKVertexAttribPosition”是顶点属性集中“位置Position”属性的索引。

顶点属性集中包含五种属性:位置、法线、颜色、纹理0,纹理1。

它们的索引值是0到4。

激活后,接下来使用“glVertexAttribPointer”方法填充数据。

iOS 开发 delegate详解

首先,让我们看看为什么要使用delegate。

一个典型的ios应用程序会有各种类型的对象:windows,tables,buttons,input boxes等等。在一个特定的应用程序中,你会让每个对象做特定的事情。比如说当用户点击一个按钮的时候,会执行一个特定的操作或者使用一个table显示特定的数据。

每个对象实例会有处理 特定 的事情。比如说我们有一个UITableView的实例,我们可能会让它以特定的方式来显示特定的 数据,同样的,我们对table的每一行进行tapping或者swiping操作的时候,它们也会做出自己特有的事件处理方式。为了避免为达到某一个特定的目的(actions or events)而创建一个子类(如果有多种不同的特定目的就会创建多个子类),你可以写出响应这些操作或者事件的方法,它们会在这些操作或者事件发生的时候被调用,为了达到此目的,你只需要给这个对象一个delegate(一个对象)。你可以使一个类作为其他一个对象或者多个对象的delegate。

简单的说代理就是在类外,让特定的人对该类做特定的操作的一种实现方法。

iOS开发中遇到的小问题-----总结

1、统一收键盘的方法

[[[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、图片的自适应功能

self.brandImage.contentMode = UIViewContentModeScaleAspectFit;

4、cocoaPods清除缓存问题

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

$ pod setup

5、设置显示键盘的样式

textView.keyboardType =UIKeyboardTypeDefault;

//设置键盘右下角为完成(中文输入法下)

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、设置placeholder属性的大小和颜色

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

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

_phoneFie.returnKeyType=UIReturnKeyDone;

9、设置cell的交互完全不可以使用

//[cellTwo setUserInteractionEnabled:NO];

//设置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); //每秒执行

dispatch_source_set_event_handler(_timer, ^{

if(timeout=0){

dispatch_source_cancel(_timer);

dispatch_async(dispatch_get_main_queue(), ^{

[btn setTitle:@"发送验证码" 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取消选中状态

[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 设置的大一些,然后给UIButton设置一个小些的图片

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

// 注意这里不能用setBackgroundImage

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

17、//避免self的强引用

__weak ViewController *weakSelf = self;

18、//类别的创建

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文件中的数据赋给数组

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

NSArray *array = [NSArrayarrayWithContentsOfFile:thePath];

22、隐藏状态栏

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

23、给navigation  Bar  设置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

//    联通号段: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、控制交易密码位数

-(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权限NSPhotoLibraryUsageDescriptionApp需要您的同意,才能访问相册NSCameraUsageDescriptionApp需要您的同意,才能访问相机NSMicrophoneUsageDescriptionApp需要您的同意,才能访问麦克风NSLocationUsageDescriptionApp需要您的同意,才能访问位置NSLocationWhenInUseUsageDescriptionApp需要您的同意,才能在使用期间访问位置NSLocationAlwaysUsageDescriptionApp需要您的同意,才能始终访问位置NSCalendarsUsageDescriptionApp需要您的同意,才能访问日历NSRemindersUsageDescriptionApp需要您的同意,才能访问提醒事项NSMotionUsageDescriptionApp需要您的同意,才能访问运动与健身NSHealthUpdateUsageDescriptionApp需要您的同意,才能访问健康更新NSHealthShareUsageDescriptionApp需要您的同意,才能访问健康分享NSBluetoothPeripheralUsageDescriptionApp需要您的同意,才能访问蓝牙NSAppleMusicUsageDescriptionApp需要您的同意,才能访问媒体资料库

34、控件设置边框

_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、系统风火轮:

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

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

AssessMentCell * cell = [tableView cellForRowAtIndexPath:indexPath];

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

//返回按钮后边文字去掉

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

forBarMetrics:UIBarMetricsDefault];

//设置左上角返回按钮的颜色

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

40、lineBreakMode //设置文字过长时的显示格式

label.lineBreakMode = NSLineBreakByCharWrapping;以字符为显示单位显

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

label.lineBreakMode = NSLineBreakByClipping;剪切与文本宽度相同的内

容长度,后半部分被删除。

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

以……方式省略,显示尾部文字内容。

label.lineBreakMode = NSLineBreakByTruncatingMiddle;中间的内容

以……方式省略,显示头尾的文字内容。

label.lineBreakMode = NSLineBreakByTruncatingTail;结尾部分的内容

以……方式省略,显示头的文字内容。

label.lineBreakMode = NSLineBreakByWordWrapping;以单词为显示单位显

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

iOS蓝牙开发:蓝牙的连接和数据的读写

蓝牙开发说简单也简单,说不简单也有点难,开发人员在首次开发蓝牙前首先需要搞清楚蓝牙开发的概念,还要了解掌握蓝牙开发的一整套流程,这样才能快速上手开发蓝牙。

  蓝牙开发分为两种模式:管理者模式和中心者模式。管理者模式基本很少用到,相当于iPhone手机作为外设,自己创建服务和特性,然后用其他设备连接iPhone手机;中心者模式一般是大部分情况下都会使用的,使用中心者模式开发相当于iPhone手机作为主机,连接蓝牙外设,下面介绍蓝牙开发的例子就是使用的中心者模式来讲解的。

在这里我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios开发的,如果你正在学习ios ,我欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2018最新的iOS进阶资料和高级开发教程

一、关于蓝牙开发的一些重要的理论概念:

1、服务(services):蓝牙外设对外广播的时候一定会有一个服务,有些时候也可以是有多个服务,服务下面包含一些特性,服务可以理解成一个模块的窗口;

2、特征(characteristic):特征存在于服务下面的,一个服务下面可以有多个特征,特征可以理解成具体实现功能的窗口,一般的特性都会有value,也就是特征值,是特征和外界交互的最小单位;

  3、UUID:蓝牙上的唯一标示符,为了区分不同服务和特征,就用UUID来表示。

二、蓝牙连接的主要步骤

 1、创建一个CBCentralManager实例来进行蓝牙管理;

 2、搜索扫描外围设备;

 3、连接外围设备;

 4、获得外围设备的服务;

 5、获得服务的特征;

 6、从外围设备读取数据;

 7、给外围设备发送(写入)数据。

三、蓝牙连接和数据读写的具体步骤

 1、导入苹果系统蓝牙框架

#import

 2、遵循两个蓝牙框架相关的协议

3、新建两个实例属性,一个特征属性

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

@property (nonatomic, strong) CBPeripheral *peripheral; //连接到的外设

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

 4、初始化CBCentralManager,进行蓝牙管理

- (void)viewDidLoad {

[super viewDidLoad];

self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];     //创建实例进行蓝牙管理

}

//若中心管理者初始化之后 就会触发下面这个代理方法 该代理方法是用来判断手机蓝牙的状态的

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

// 蓝牙可用,开始扫描外设

if (central.state == CBManagerStatePoweredOn) {

NSLog(@"蓝牙可用");

//在中心管理者成功开启之后再进行一些操作

//搜索扫描外设

// 根据SERVICE_UUID来扫描外设,如果不设置SERVICE_UUID,则扫描所有蓝牙设备

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

[central scanForPeripheralsWithServices:nil options:nil];

}

if(central.state == CBManagerStateUnsupported) {

NSLog(@"该设备不支持蓝牙");

}

if (central.state == CBManagerStatePoweredOff) {

NSLog(@"蓝牙已关闭");

}

if (central.state == CBManagerStateUnknown) {

NSLog(@"蓝牙当前状态不明确");

}

if (central.state == CBManagerStateUnauthorized) {

NSLog(@"蓝牙未被授权");

}

}

  5、搜索外围设备

//执行扫描动作之后,如果扫描到外设了,就会自动回调下面的协议方法

/** 发现符合要求的外设,回调 */

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

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

//根据外设名字有选择性的筛选连接蓝牙设备

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

//在这里对外设携带的广播数据进行进一步的处理

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

//如果数组中包含了就不再添加

return;

}

//添加到外设名字数组中

[self.peripheraNames addObject:peripheral.name];

//标记外设,让它的生命周期与控制器的一致

self.peripheral = peripheral;

// 可以根据外设名字来过滤外设

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

}

// 连接外设

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

}

6、连接外围设备

//连接外围设备,中心管理者连接外设成功,如果连接成功就会回调这个协议方法

/** 连接成功 */

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

//连接成功之后,可以进行服务和特性的发现。 停止中心管理设备的扫描动作,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为iOS BLE4.0是支持一对多连接的),导致数据的混乱。

//停止扫描动作

[self.centralManager stopScan];

// 设置外设的代理

peripheral.delegate = self;

// 根据UUID来寻找服务

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

//外设发现服务,传nil代表不过滤,一次性读出外设的所有服务

[peripheral discoverServices:nil];

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

}

//外设连接失败

/** 连接失败的回调 */

- (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);

// 断开连接可以设置重新连接

[central connectPeripheral:peripheral options:nil];

}

7、获取外围设备服务和特征

/** 发现服务 */

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

// 遍历出外设中所有的服务

for (CBService *service in peripheral.services) {

// NSLog(@"所有的服务:%@",service);

}

// 这里仅有一个服务,所以直接获取

CBService *service = peripheral.services.lastObject;

// 根据UUID寻找服务中的特征

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

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

[peripheral discoverCharacteristics:nil forService:service];

}

8、从外围设备读取数据

// 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法) 你可以判断是否 从外围设备读数据

/** 接收到数据回调 */

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

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

// //characteristic.value就是你要的数据

// }

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

NSData *data = characteristic.value;

NSString *value = [self hexadecimalString:data];

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

}

// 拿到外设发送过来的数据

// NSData *data = characteristic.value;

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

}

9、向外围设备发送(写入)数据

//这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用

//[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];//第一个参数是已连接的蓝牙设备; 第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入 需要注意的是特征的属性是否支持写数据

/** 写入数据回调 */

- (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

};

打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值

常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式

*/

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

// 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含

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

}

10、具体调用给蓝牙外设写入数据方法,这里的例子是以按钮点击事件里面来调用处理

//发送按钮点击事件

- (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];

// 根据上面的特征self.characteristic来写入数据

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


当前标题:ios开发实例教程,ios程序设计及实践
当前路径:http://kswsj.cn/article/dscgjss.html

其他资讯