iOS学习笔记30-系统服务(三)蓝牙

一、蓝牙

随着蓝牙低功耗技术BLE(Bluetooth Low Energy)的发展,蓝牙技术正在一步步成熟,如今的大部分移动设备都配备有蓝牙4.0,相比之前的蓝牙技术耗电量大大降低。

在iOS中进行蓝牙传输常用的框架有如下几种:
  1. GameKit.framework

    iOS7之前的蓝牙框架,只可用于同应用之间的蓝牙传输。

  2. MultipeerConnectivity.framework

    iOS7开始引入的蓝牙框架,用于取代GameKit,也有缺陷,仅支持iOS设备之间蓝牙传输。

  3. CoreBluetooth.framework

    功能强大的蓝牙框架,但要求设备必须支持蓝牙4.0,可以支持所有设备蓝牙传输,只要该设备支持蓝牙4.0。

应用的比较多的是CoreBluetooth框架,这里就选择CoreBluetooth框架来讲。

二、CoreBluetooth

当前BLE应用相当广泛,不再仅仅是两个设备之间的数据传输,它还有很多其他应用市场,例如室内定位、无线支付、智能家居等等,这也使得CoreBluetooth成为当前最热门的蓝牙技术。

我的理解中,CoreBluetooth蓝牙通信过程和网络通信过程比较类似。

CoreBluetooth中,蓝牙传输都分为两个部分:
  1. 外围设备CBPeripheral

    负责发布并广播服务,告诉周围的中央设备它的可用服务和特征,类似于网络通信中的服务端。

  2. 中央设备CBCentral

    负责和外围设备建立连接,一旦连接成功就可以使用外围设备的服务和特征,类似于网络通信中的客户端

外围设备和中央设备交互的桥梁是服务特征,两个都有一个唯一标识CBUUID来确定一个服务或者特征:

* 服务CBService

中央设备只有通过服务才能与外围设备进行数据传输,类似于客户端通过网址URL才能与服务器连接一样

* 特征CBCharacteristic

每个服务可以拥有多个特征,中央设备必须订阅外围设备服务的特征值,才能获取外围设备的数据,类似于GET请求可以请求获取服务器数据,POST请求可以向服务器传输数据一样。

三、设备作为外围设备

设备作为外围设备的创建步骤:
  1. 创建外围设备管理器CBPeripheralManager,并设置代理
  2. 创建一个特征CBCharacteristic,绑定一个CBUUID,设置特征属性
  3. 创建一个服务CBService,绑定一个CBUUID,设置服务的特征
  4. 调用外围设备管理器的对象方法,添加服务到外围设备上
-(void)addService:(CBService *)service;
  1. 外围设备管理器开始广播服务
-(void)startAdvertising:(NSDictionary *)dict;
  1. 在外围设备管理器的代理方法,处理与中央设备的交互

外围设备管理器启动服务的相关代理方法:
/* 外围设备管理器状态发生改变后调用,比如外围设备打开蓝牙的时候 */
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;
/* 外围设备管理器添加了服务后调用,一般在这里进行广播服务 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
            didAddService:(CBService *)service /* 添加的服务 */
                    error:(NSError *)error;/* 添加服务错误信息 */
/* 启动广播服务后调用 */
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
                                       error:(NSError *)error;/* 启动服务错误信息 */
/* 外围设备恢复状态时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
         willRestoreState:(NSDictionary *)dict;
外围设备管理器和中央设备进行交互的代理方法:
/* 中央设备订阅外围设备的特征时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral /* 外围设备管理器 */
                  central:(CBCentral *)central /* 中央设备 */
        didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;/* 订阅的特征 */
/* 中央设备取消订阅外围设备的特征时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral /* 外围设备管理器 */
                  central:(CBCentral *)central /* 中央设备 */
        didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic;/* 特征 */
/* 外围设备收到中央设备的写请求时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
        didReceiveWriteRequests:(CBATTRequest *)request;/* 写请求 */
外围设备管理器CBPeripheralManager的常用对象方法:
/* 添加服务 */
- (void)addService:(CBService *)service;
/* 开启广播服务,dict设置设备信息 */
- (void)startAdvertising:(NSDictionary *)dict;
/* 更新特征值,centrals为空,表示对所有连接的中央设备通知 */
- (void)updateValue:(NSData *)value /* 特征的特征值 */
        forCharacteristic:(CBCharacteristic *)characteristic /* 特征 */
        onSubscribedCentrals:(NSArray *)centrals;/* 需要通知更新特征值的中央设备 */
下面是设备作为外围设备的实例:
#import "PeripheralViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>

#define kPeripheralName         @"Liuting‘s Device" //外围设备名称,自定义
#define kServiceUUID           @"FFA0-FFB0" //服务的UUID,自定义
#define kCharacteristicUUID     @"FFCC-FFDD" //特征的UUID,自定义

@interface PeripheralViewController ()<CBPeripheralManagerDelegate>
@property (strong, nonatomic) CBPeripheralManager *peripheralManager;/* 外围设备管理器 */
@property (strong, nonatomic) NSMutableArray *centralM;/* 订阅的中央设备 */
@property (strong, nonatomic) CBMutableCharacteristic *characteristicM;/* 特征 */
@end
@implementation PeripheralViewController
- (void)viewDidLoad{
    [super viewDidLoad];
    self.centralM = [NSMutableArray array];
    //创建外围设备管理器
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
                                                                     queue:nil];
}
#pragma mark - UI事件
/* 点击更新特征值 */
- (IBAction)changeCharacteristicValue:(id)sender {
    //特征值,这里是更新特征值为当前时间
    NSString *valueStr = [NSString stringWithFormat:@"%@",[NSDate date]];
    NSData *value = [valueStr dataUsingEncoding:NSUTF8StringEncoding];
    //更新特征值
    [self.peripheralManager updateValue:value
                      forCharacteristic:self.characteristicM
                   onSubscribedCentrals:nil];
}
#pragma mark - 私有方法
/* 创建特征、服务并添加服务到外围设备 */
- (void)addMyService{
    /*1.创建特征*/
    //创建特征的UUID对象
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    /* 创建特征
     * 参数
     * uuid:特征标识
     * properties:特征的属性,例如:可通知、可写、可读等
     * value:特征值
     * permissions:特征的权限
     */
    CBMutableCharacteristic *characteristicM =
        [[CBMutableCharacteristic alloc] initWithType:characteristicUUID
                                           properties:CBCharacteristicPropertyNotify
                                                value:nil
                                          permissions:CBAttributePermissionsReadable];
    self.characteristicM = characteristicM;
    //创建服务UUID对象
    CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
    //创建服务
    CBMutableService *serviceM = [[CBMutableService alloc] initWithType:serviceUUID
                                                                primary:YES];
    //设置服务的特征
    [serviceM setCharacteristics:@[characteristicM]];
    //将服务添加到外围设备
    [self.peripheralManager addService:serviceM];
}

#pragma mark - CBPeripheralManager代理方法
/* 外围设备状态发生变化后调用 */
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    //判断外围设备管理器状态
    switch (peripheral.state) {
        case CBPeripheralManagerStatePoweredOn:
        {
            NSLog(@"BLE已打开.");
            //添加服务
            [self addMyService];
            break;
        }
        default:
        {
            NSLog(@"此设备不支持BLE或未打开蓝牙功能,无法作为外围设备.");
            break;
        }
    }
}
/* 外围设备恢复状态时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
         willRestoreState:(NSDictionary *)dict
{
    NSLog(@"状态恢复");
}
/* 外围设备管理器添加服务后调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
            didAddService:(CBService *)service
                   error:(NSError *)error
{
    //设置设备信息dict,CBAdvertisementDataLocalNameKey是设置设备名
    NSDictionary *dict = @{CBAdvertisementDataLocalNameKey:kPeripheralName};
    //开始广播
    [self.peripheralManager startAdvertising:dict];
    NSLog(@"向外围设备添加了服务并开始广播...");
}
/* 外围设备管理器启动广播后调用 */
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
                                       error:(NSError *)error
{
    if (error) {
        NSLog(@"启动广播过程中发生错误,错误信息:%@",error.localizedDescription);
        return;
    }
    NSLog(@"启动广播...");
}
/* 中央设备订阅特征时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
                  central:(CBCentral *)central
        didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
{
    NSLog(@"中心设备:%@ 已订阅特征:%@.",central,characteristic);
    //把订阅的中央设备存储下来
    if (![self.centralM containsObject:central]) {
        [self.centralM addObject:central];
    }
}
/* 中央设备取消订阅特征时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
                 central:(CBCentral *)central
        didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
{
    NSLog(@"中心设备:%@ 取消订阅特征:%@",central,characteristic);
}

/* 外围设备管理器收到中央设备写请求时调用 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral
        didReceiveWriteRequests:(CBATTRequest *)request
{
    NSLog(@"收到写请求");
}
@end

四、设备作为中央设备

更多的时候,我们需要的是一个中央设备,外围设备不一定是iOS设备,所以上面外围设备的创建不一定会用到,比如外围设备是GPS导航仪、心率仪等,这些只要遵循BLE4.0的规范,中央设备就可以与之连接并寻找服务和订阅特征。

设备作为中央设备的创建步骤:
  1. 创建中央设备管理器对象CBCentralManager,设置代理
  2. 扫描外围设备,发现外围设备CBPeripheral进行连接,保持连接的外围设备
  3. 在连接外围设备成功的代理方法中,设置外围设备的代理,调用外围设备的对象方法寻找服务
  4. 查找外围设备的服务和特征,查找到可用特征,则读取特征数据。
    • **记住这里是外围设备对象CBPeripheral

      不是上面的外围设备管理器对象CBPeripheralManager**

中央设备管理器的代理方法:
/* 中央设备管理器状态改变后调用,比如蓝牙的打开与关闭 */
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;
/* 开启扫描后,中央设备管理器发现外围设备后调用 */
- (void)centralManager:(CBCentralManager *)central
        didDiscoverPeripheral:(CBPeripheral *)peripheral /* 外围设备 */
            advertisementData:(NSDictionary *)advertisementData /* 设备信息 */
                         RSSI:(NSNumber *)RSSI; /* 信号强度 */
/* 中央设备管理器成功连接到外围设备后调用 */
- (void)centralManager:(CBCentralManager *)central
  didConnectPeripheral:(CBPeripheral *)peripheral;/* 外围设备 */
/* 中央设备管理器连接外围设备失败后调用 */
- (void)centralManager:(CBCentralManager *)central
        didFailToConnectPeripheral:(CBPeripheral *)peripheral /* 外围设备 */
                             error:(NSError *)error;/* 连接失败的错误信息 */
中央设备管理器的对象方法:
/* 扫描外围设备,可以指定含有指定服务的外围设备 */
- (void)scanForPeripheralsWithServices:(NSArray<CBUUID *> *)services
                               options:(NSDictionary *)options;
/* 停止扫描 */
- (void)stopScan;
/* 连接外围设备 */
- (void)connectPeripheral:(CBPeripheral *)peripheral
                  options:(NSDictionary *)options;
/* 断开外围设备 */
- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral;
外围设备的代理方法【和上面的外围设备管理器代理不一样】
/**
 *  1.成功订阅外围设备的服务后调用,在该代理方法中寻找服务的特征
 *  @param peripheral 连接到的设备
 *  @param error       错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral
        didDiscoverServices:(NSError *)error;
/**
 *  2.成功找到外围设备服务的特征后调用,在该代理方法中设置订阅方式
 *  @param peripheral 连接的设备
 *  @param service     拥有的服务
 *  @param error       错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral
        didDiscoverCharacteristicsForService:(CBService *)service
             error:(NSError *)error;
/**
 *  3.外围设备读取到特征值就会调用
 *  @param peripheral    连接的设备
 *  @param characteristic 改变的特征
 *  @param error          错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral
        didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error;
/**
 *  4.向外围设备的特征对象写操作完成后调用
 *  特别:当写操作为CBCharacteristicWriteWithoutResponse时不会调用
 *  @param peripheral    连接的设备
 *  @param characteristic 要写入的特征
 *  @param error          错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral
        didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error;
外围设备CBPeripheral的常用对象方法:
/* 寻找服务,传入的是服务的唯一标识CBUUID */
- (void)discoverServices:(NSArray<CBUUID *> *)services;
/* 寻找指定服务下的特征,特征数组也是传入特征的唯一标识CBUUID */
- (void)discoverCharacteristics:(NSArray<CBUUID *> *)characteristics
                     forService:(CBService *)service;/* 服务 */
/* 设置是否向特征订阅数据实时通知,YES表示会实时多次会调用代理方法读取数据 */
- (void)setNotifyValue:(BOOL)value
     forCharacteristic:(CBCharacteristic *)characteristic;
/* 读取特征的数据,调用此方法后会调用一次代理方法读取数据 */
- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
/* 向特征写入数据,看type类型,决定调不调用写入数据后回调的代理方法 */
- (void)writeValue:(NSData *)value /* 写入数据 */
 forCharacteristic:(CBCharacteristic *)characteristic /* 特征 */
              type:(CBCharacteristicWriteType)type;/* 写入类型 */
写入类型目前只有2种方式:
/* 写入类型,决定要不要调用代理方法 */
typedef NS_ENUM(NSInteger, CBCharacteristicWriteType) {
    CBCharacteristicWriteWithResponse = 0, //有回调的写入
    CBCharacteristicWriteWithoutResponse //没回调的写入
};
下面是设备作为中央设备的实例:
#import "CentralViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>

#define kPeripheralName         @"Liuting‘s Device" //外围设备名称
#define kServiceUUID           @"FFA0-FFB0" //服务的UUID
#define kCharacteristicUUID     @"FFCC-FFDD" //特征的UUID

@interface CentralViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (strong, nonatomic) CBCentralManager *centralManager;/* 中央设备管理器 */
@property (strong, nonatomic) NSMutableArray *peripherals;/* 连接的外围设备 */
@end
@implementation CentralViewController
#pragma mark - UI事件
- (void)viewDidLoad{
    [super viewDidLoad];
    self.peripherals = [NSMutableArray array];
    //创建中心设备管理器并设置当前控制器视图为代理
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
#pragma mark - CBCentralManager代理方法
/* 中央设备管理器状态更新后调用 */
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
    case CBPeripheralManagerStatePoweredOn:
        NSLog(@"BLE已打开.");
        //扫描外围设备
        [central scanForPeripheralsWithServices:nil options:nil];
        break;
    default:
        NSLog(@"此设备不支持BLE或未打开蓝牙功能,无法作为中央设备.");
        break;
    }
}
/*
 *  发现外围设备调用
 *  @param central           中央设备管理器
 *  @param peripheral        外围设备
 *  @param advertisementData 设备信息
 *  @param RSSI              信号质量(信号强度)
 */
- (void)centralManager:(CBCentralManager *)central
        didDiscoverPeripheral:(CBPeripheral *)peripheral
            advertisementData:(NSDictionary *)advertisementData
                         RSSI:(NSNumber *)RSSI
{
    NSLog(@"发现外围设备...");
    //连接指定的外围设备,匹配设备名
    if ([peripheral.name isEqualToString:kPeripheralName]) {
        //添加保存外围设备,因为在此方法调用完外围设备对象就会被销毁
        if(![self.peripherals containsObject:peripheral]){
            [self.peripherals addObject:peripheral];
        }
        NSLog(@"开始连接外围设备...");
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}
/* 中央设备管理器成功连接到外围设备后调用 */
- (void)centralManager:(CBCentralManager *)central
        didConnectPeripheral:(CBPeripheral *)peripheral
        {
    NSLog(@"连接外围设备成功!");

    //停止扫描
    [self.centralManager stopScan];
    //设置外围设备的代理为当前视图控制器
    peripheral.delegate = self;
    //外围设备开始寻找服务
    [peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
}
/* 中央设备管理器连接外围设备失败后调用 */
- (void)centralManager:(CBCentralManager *)central
        didFailToConnectPeripheral:(CBPeripheral *)peripheral
                             error:(NSError *)error
 {
     NSLog(@"连接外围设备失败!");
 }
 #pragma mark - CBPeripheral 代理方法
/* 外围设备寻找到服务后调用 */
- (void)peripheral:(CBPeripheral *)peripheral
        didDiscoverServices:(NSError *)error
{
    NSLog(@"已发现可用服务...");
    //遍历查找到的服务
    CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    for (CBService *service in peripheral.services) {
        if([service.UUID isEqual:serviceUUID]){
            //外围设备查找指定服务中的特征,characteristics为nil,表示寻找所有特征
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }
}
/* 外围设备寻找到特征后调用 */
- (void)peripheral:(CBPeripheral *)peripheral
        didDiscoverCharacteristicsForService:(CBService *)service
             error:(NSError *)error
{
    NSLog(@"已发现可用特征...");
    //遍历服务中的特征
    CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    if ([service.UUID isEqual:serviceUUID]) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            if ([characteristic.UUID isEqual:characteristicUUID]) {
                //情景一:通知
                /* 找到特征后设置外围设备为已通知状态(订阅特征):
                * 调用此方法会触发代理方法peripheral:didUpdateValueForCharacteristic:error:
                * 调用此方法会触发外围设备管理器的订阅代理方法
                */
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];

                //情景二:读取
                //调用此方法会触发代理方法peripheral:didUpdateValueForCharacteristic:error:
                //[peripheral readValueForCharacteristic:characteristic];
            }
        }
    }
}
/* 外围设备读取到特征值后调用 */
- (void)peripheral:(CBPeripheral *)peripheral
        didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error
{
    if (characteristic.value) {
        NSString *value = [[NSString alloc] initWithData:characteristic.value
                                                encoding:NSUTF8StringEncoding];
        NSLog(@"读取到特征值:%@",value);
    }else{
        NSLog(@"未发现特征值.");
    }
}
@end

五、蓝牙后台运行

除非去申请后台权限,否则 app 都是只在前台运行的,程序在进入后台不久便会切换到挂起状态。挂起后,程序将无法再接收任何蓝牙事件。

中央设备管理器连接外围设备的方法中的options属性,可以设置如下字典值:
  • CBConnectPeripheralOptionNotifyOnConnectionKey

    在连接成功后,程序被挂起,给出系统提示。

  • CBConnectPeripheralOptionNotifyOnDisconnectionKey

    在程序挂起,蓝牙连接断开时,给出系统提示。

  • CBConnectPeripheralOptionNotifyOnNotificationKey

    在程序挂起后,收到 peripheral 数据时,给出系统提示。

设置蓝牙后台模式:
  • 添加info.plist字段Required background nodes
  • 在该字段下添加字符串值:
    • App communicates using CoreBluetooth:表示支持设备作为中央设备后台运行
    • App shares data using CoreBluetooth:表示支持设备作为外围设备后台运行

设备作为中央设备的后台运行和前台运行区别:
  • 会将发现的多个外围设备的广播数据包合并为一个事件,然后每找到一个外围设备都会调用发现外围设备的代理方法
  • 如果全部的应用都在后台搜索外围设备,那么每次搜索的时间间隔会更大。这会导致搜索到外围设备的时间变长
设备作为外围设备的后台运行和前台运行区别:
  • 在广播时,广播数据将不再包含外围设备的名字
  • 外围设备只能被明确标识了搜索服务UUID的iOS设备找到
  • 如果所有应用都在后台发起广播,那么发起频率会降低

关于后台运行的细节,可以参考:CoreBluetooth8 后台运行蓝牙服务

上面的代码Demo点这里:LearnDemo里面的BluetoothDemo

有什么问题在下方评论区中提出!O(∩_∩)O哈!
时间: 2024-11-09 03:45:20

iOS学习笔记30-系统服务(三)蓝牙的相关文章

iOS学习笔记14-网络(三)WebView

一.WebView WebView就是一个内嵌浏览器控件,在iOS中主要有两种WebView:UIWebView和WKWebView,UIWebView是iOS2之后开始使用,WKWebView是在iOS8开始使用,毫无疑问WKWebView将逐步取代笨重的UIWebView. WKWebView的优点: WKWebView更多的支持HTML5的特性 WKWebView更快,占用内存可能只有UIWebView的1/3 ~ 1/4 WKWebView高达60fps的滚动刷新率和丰富的内置手势 WK

iOS学习笔记---oc语言第三天

继承.初始化方法 一.继承 继承的上层:父类  继承的下层:子类 继承是单向的,不能相互继承 继承具有传递性:A继承于B,B继承于C,A具有B和C的特征和行为 子类能继承父类全部的特征和行为(私有变量也继承过来了,只是不能访问) 面向对象提供了继承语法.能大大简化代码,把公共的方法和实例对象写在父类里.子类只需要写自己独有的实例变量和方法即可 继承既能保证类的完整,又能简化代码 继承特点 oc中只允许单继承 没有父类的类称为根类,oc中得根类是NSObject(祖宗) 继承的内容:所有的实例变量

iOS学习笔记-精华整理

iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始等待用户的操作,自动释放池就会被释放掉(调用dealloc),池中的对象都会收到一个release,有可能会因此被销毁. 2-成员属性:     readonly:不指定readonly,默认合成getter和setter方法.外界毫不关心的成员,则不要设置任何属性,这样封装能增加代码的独立性和安全

iOS学习笔记---c语言第九天

高级指针 指向结构体变量的指针,称为结构体指针 可以使用->指向内容. %p打印地址 void pLenth(cPoint *p1,cPoint *p2) //求两点间的距离  用的开方函数sqrt()和平方函数pow(,) { float a = sqrt(pow((p1->x-p2->x), 2)+pow((p1->y-p2->y), 2)); printf("两点距离为%.2f\n",a); } //main.m中代码 #import <Fou

IOS学习笔记---C语言第四天

1 //?生成2个数组,每个数组都有10个元素,元素取值范围20-40之间,数组对应元素相 加,放到另外?一个数组中 2 #import <Foundation/Foundation.h> 3 4 int main(int argc, const char * argv[]) 5 { 6 7 int num1[10]={0},num2[10]={0},num3[10]={0}; 8 for (int i = 0; i<10; i++) { 9 num1[i]=arc4random()%2

iOS学习笔记---c语言学习第七天

结构体 结构体是一种自定义的数据类型 struct 结构体名 { 类型说明符  成员名: … 类型说明符  成员名: }: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { struct teacher{ char name[30]; char sex; int age; char course[30]; }; typedef struct teacher Teacher; Teacher c

iOS学习笔记---c语言第十一天

函数指针 一.函数指针定义 //函数声明:声明我是一个什么函数 //求两个数的和 //函数的类型:int (int x,int y) //即:我是一个返回值为整型,有两个整型参数的函数. //函数名是 sum int sum(int x,int y); 函数指针定义p是变量,其他是类型(通常没有形参a,b) //函数指针类型 int (*)(int x,int y) //描述:指向 返回值为 int 两个int参数 的 指针类型 //函数指针变量: p //初始值 : sum printf("%

iOS学习笔记之UITableViewController&amp;UITableView

iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论文,因此需要继续思考新的算法.这是一件挺痛苦的事情,特别是在很难找到与自己研究方向相关的文献的时候.也许网格序列水印这个课题本身的研究意义就是有待考证的.尽管如此,还是要努力的思考下去.由于实验室的原因,iOS的学习进度明显受到影响,加之整理文档本身是一件耗费时间和精力的事情,因此才这么久没有写笔记了. M

IOS学习笔记 -- Modal和Quartz2D

一. Modal1.Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止;Modal只是改变了View的现实,没有改变rootViewController 2.常用方法1>.以Modal的形式展示控制器- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion2>.关

iOS: 学习笔记, 添加一个带界面约束的控制器

1. 创建一个空iOS应用程序(Empty Application). 2. 添加加控制器类. 修改控制器类的viewDidLoad 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 //创建标题 5 UILabel *header = [[UILabel alloc] init]; 6 header.text = @"欢迎来到我的世界!"; 7 header.textAlignment = NSTextAlignmentCenter