初认Objective-c NSNumber NSInteger int NSNumber转换

本文详细介绍了Objective-C中NSNumber的使用方法,包括不同类型的数值对象创建、数值对象间的比较及数值与字符串之间的转换技巧。
    在Objective-c中有int的数据类型,还要用NSNumber?这是因为int不是对象。
NSNumber是数据对象,我们可以使用NSNumber数据对象来创建和初始化不同类型的数字对象。
    #import <Foundation/Foundation.h>  
      
    NSNumber *myNumber,*floatNumber,*intNumber,*number1;  
      
    //创建integer类型对象  
    intNumber = [NSNumber numberWithInteger:123];  
    NSLog(@"%i",[intNumber integerValue]);  
      
    //创建long类型对象  
    myNumber = [NSNumber numberWithLong:0xababab];  
    NSLog(@"%lx",[myNumber longValue]);  
      
    //创建char类型对象  
    myNumber = [NSNumber numberWithChar:'K'];  
    NSLog(@"%c",[myNumber charValue]);  
      
    //创建float类型对象  
    floatNumber = [NSNumber numberWithFloat:123.00];  
    NSLog(@"%f",[floatNumber floatValue]);  
      
    //创建double类型对象  
    myNumber = [NSNumber numberWithDouble:112233e+15];  
    NSLog(@"%lg",[myNumber doubleValue]);  
      
    //判断两个对象的值是否相等  
    if ([intNumber isEqualToNumber:floatNumber] == YES ) {  
       NSLog(@"值相等");  
    } else {  
       NSLog(@"值不相等");  
    }  
      
    //比较两个对象的值大小  
    if ( [intNumber compare:myNumber] == NSOrderedAscending) {  
       NSLog(@"左边的数字小");  
    } else {  
       NSLog(@"左边的数字大");  
    }  
      
    //初始化实例  
    number1 = [[NSNumber alloc] initWithInt:1000];  
    NSLog(@"%d",[number1 intValueunsigned];  
    [number1 release];  
   对于每个数字基本类型,类方法都为这它分配了一个NSNumber对象,并将其设置为指定的值,这些方法都是以numberWith开始的,之后是类型,如numberWithLong。

此外,还可以使用实例方法为先前分配的NSNumber对象设定指定的值,这些都是以initWith开头,比如initWithLong。


对于初学者来说,那么问题来了?那么说到int他和NSInteger又有什么区别呢?

在c语言中,int和long的字节数是和操作系统指针所占位数相等。

但c语言中说,long的长度永远大于或等于int

objective-c里,苹果的官方文档中总是推荐用NSInteger

它和int有什么区别呢,stackoverflow这帮大神给了答案。

原来在苹果的api实现中,NSInteger是一个封装,它会识别当前操作系统的位数,自动返回最大的类型。

定义的代码类似于下:

 

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64

typedef long NSInteger;

typedef unsigned long NSUInteger;

#else

typedef int NSInteger;

typedef unsigned int NSUInteger;

#endif

很简单的总结:那就是NSInteger与int的区别是NSInteger会根据系统的位数(32or64)自动选择int的最大数值(int or long)还有就是他和NSString一样都可以是对象。


最后我们再来扯一扯objective-c中数字型字符串转换NSNumber:

我们首先写个方法如下:

    id result;  
      
    NSString * ss;  
      
      
      
    ss=@"124";  
      
      
      
    result=[NSNumber numberWithFloat:[ss floatValue]];     
      
    NSLog(@"%f",[ss floatValue]);  
      
    NSLog(@"%f",[result floatValue]);   

直接将NSString类的floatValue方法将ss对象转成float类型,再使用NSNumber的numberWithFloat方法转成NSNumber类型的对象。

但这里有一个问题,如果ss不是@”111.22”,而是@“xxx”,则该方法将报错的。

因此,这里需要一个事先判断,判断ss是不是能转成成NSNumber。

根据这个修改要求,我再将代码转换成这样:

ss=@"224.34129";  
  
  
  
  NSNumberFormatter *f = [[NSNumberFormatter alloc] init];  
  
  
  
  if ([f numberFromString:ss])  
  
  {  
  
      result=[NSNumber numberWithFloat:[ss floatValue]];  
  
  }  
  
  else  
  
  {  
  
      result=ss;  
  
  }  
  
  NSLog(@"%.2f",[result floatValue]);

这样,功能是没有问题了。但看过之后,觉得有点累赘感。

代码简洁点可不可以呢?最终修改成这样几行,如下所示:

ss=@"324.34";  
  
 result=[f numberFromString:ss];  
  
 if(!(result))  
  
 {  
  
     result=ss;  
  
 }  
   
 NSLog(@"%.2f",[result floatValue]); 

测试结果如下: 

2012-08-07 17:35:04.203 apple1[2484] 124.000000

2012-08-07 17:35:04.203 apple1[2484] 124.000000

2012-08-07 17:35:04.203 apple1[2484] 224.34

2012-08-07 17:35:04.203 apple1[2484] 324.34

<think>我们正在讨论如何通过WiFi检测外接相机。在iOS中,检测通过WiFi连接的外部相机通常涉及使用网络服务发现协议(如Bonjour)或直接IP连接。以下是一种可能的方法: 1. **使用Bonjour服务发现**:许多网络相机支持Bonjour(即mDNS)来自动广播其服务。我们可以使用`NSNetServiceBrowser`来搜索相机服务。 2. **手动扫描特定端口**:如果知道相机使用的端口(例如HTTP的80端口或RTSP的554端口),可以尝试扫描本地网络上的设备。 3. **使用特定相机的SDK**:一些相机制造商提供SDK来简化连接过程。 由于问题中要求使用Objective-C,下面我们将重点放在使用Bonjour发现网络相机。 ### 步骤1:使用Bonjour发现网络相机 Bonjour允许设备在本地网络上广播服务。相机通常会发布一个服务,例如`_http._tcp`(用于HTTP服务)或特定于相机的服务类型(如`_ptp._tcp`用于图片传输协议)。 我们可以使用`NSNetServiceBrowser`来搜索这些服务。 #### 代码示例: ```objective-c #import <Foundation/Foundation.h> @interface CameraDiscovery : NSObject <NSNetServiceBrowserDelegate, NSNetServiceDelegate> @property (nonatomic, strong) NSNetServiceBrowser *serviceBrowser; @property (nonatomic, strong) NSMutableArray<NSNetService *> *discoveredCameras; @end @implementation CameraDiscovery - (instancetype)init { self = [super init]; if (self) { _discoveredCameras = [NSMutableArray array]; } return self; } - (void)startDiscovery { // 停止之前的搜索 [self stopDiscovery]; // 创建并启动服务浏览器 self.serviceBrowser = [[NSNetServiceBrowser alloc] init]; self.serviceBrowser.delegate = self; // 搜索所有PTP(图片传输协议)相机服务,也可以尝试其他类型,如"_http._tcp" [self.serviceBrowser searchForServicesOfType:@"_ptp._tcp" inDomain:@"local."]; } - (void)stopDiscovery { [self.serviceBrowser stop]; self.serviceBrowser = nil; } #pragma mark - NSNetServiceBrowserDelegate // 发现服务 - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing { // 将服务添加到数组并开始解析 [self.discoveredCameras addObject:service]; service.delegate = self; [service resolveWithTimeout:5.0]; } - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)moreComing { [self.discoveredCameras removeObject:service]; } #pragma mark - NSNetServiceDelegate // 解析服务成功 - (void)netServiceDidResolveAddress:(NSNetService *)sender { // 获取主机名和端口 NSString *hostName = sender.hostName; NSInteger port = sender.port; NSLog(@"发现相机: %@:%ld", hostName, (long)port); // 这里可以进一步连接相机,例如通过PTP协议或HTTP协议 } // 解析失败 - (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary<NSString *, NSNumber *> *)errorDict { NSLog(@"解析服务失败: %@", errorDict); } @end ``` ### 步骤2:连接相机 一旦我们解析出相机的主机名和端口,就可以根据相机支持的协议进行连接。例如,如果相机支持HTTP,我们可以用`NSURLSession`发送请求;如果支持PTP/IP协议,则需要实现相应的协议。 ### 注意事项 1. **服务类型**:上述代码使用了`_ptp._tcp`服务类型,但并非所有相机都支持。常见的服务类型包括: - `_http._tcp`:用于通过网页界面控制的相机。 - `_ipp._tcp`:互联网打印协议,有时相机也使用。 - `_printer._tcp`:打印机,但有时相机也可能误用。 - 特定相机的服务类型,例如佳能相机可能使用`_canon_cnp._tcp`。 2. **手动扫描**:如果Bonjour不可用,可能需要手动扫描IP地址范围并尝试连接已知端口。这可以使用`GCDAsyncSocket`等第三方库进行端口扫描,但效率较低。 3. **使用特定SDK**:对于特定品牌的相机(如佳能、尼康),最好使用厂商提供的SDK,因为它们通常封装了网络发现和连接功能。 ### 总结 在Objective-C中,通过WiFi检测外接相机主要依赖于Bonjour服务发现。我们使用`NSNetServiceBrowser`搜索特定类型的服务(如`_ptp._tcp`),然后解析找到的服务以获取主机名和端口。之后,根据相机支持的协议进行连接。 §§相关问题§§ 1. iOS中Bonjour服务发现的具体流程是什么? 2. 如何手动扫描本地网络上的设备? 3. 在iOS中如何实现PTP协议与相机通信? 4. 有哪些第三方库可以简化iOS与网络相机的连接? 5. 如何处理不同品牌相机的兼容性问题?</think>### 在 Objective-C 中检测 WiFi 外接相机的方法 在 iOS 平台上检测通过 WiFi 连接的外部相机,主要涉及网络服务发现和相机协议处理。以下是完整实现方案: #### 1. **使用 Bonjour 服务发现** Bonjour (mDNS) 是 Apple 的零配置网络协议,用于发现局域网中的设备和服务: ```objective-c #import <Foundation/Foundation.h> @interface CameraScanner : NSObject <NSNetServiceBrowserDelegate, NSNetServiceDelegate> @property (nonatomic, strong) NSNetServiceBrowser *serviceBrowser; @property (nonatomic, strong) NSMutableArray<NSNetService *> *discoveredCameras; @end @implementation CameraScanner - (void)startScanning { self.serviceBrowser = [[NSNetServiceBrowser alloc] init]; self.serviceBrowser.delegate = self; self.discoveredCameras = [NSMutableArray array]; // 搜索 PTP/IP 相机协议服务(常见于数码相机) [self.serviceBrowser searchForServicesOfType:@"_ptp._tcp" inDomain:@"local."]; // 搜索通用相机服务 [self.serviceBrowser searchForServicesOfType:@"_camera._tcp" inDomain:@"local."]; } #pragma mark - NSNetServiceBrowserDelegate - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing { [self.discoveredCameras addObject:service]; service.delegate = self; [service resolveWithTimeout:5.0]; // 解析服务详情 } - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)moreComing { [self.discoveredCameras removeObject:service]; } #pragma mark - NSNetServiceDelegate - (void)netServiceDidResolveAddress:(NSNetService *)sender { NSLog(@"发现相机: %@, IP: %@, Port: %ld", sender.name, [self getIPFromAddressData:sender.addresses.firstObject], (long)sender.port); } - (NSString *)getIPFromAddressData:(NSData *)data { struct sockaddr *addr = (struct sockaddr *)data.bytes; if(addr->sa_family == AF_INET) { char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), ip, sizeof(ip)); return [NSString stringWithUTF8String:ip]; } return @"Unknown"; } @end ``` #### 2. **手动扫描网络设备** 如果 Bonjour 不可用,可扫描本地网络段: ```objective-c #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> - (void)scanLocalNetwork { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ const char *baseIP = "192.168.1."; // 根据实际网络修改 int port = 15740; // PTP/IP 标准端口 for(int i = 1; i < 255; i++) { char fullIP[20]; sprintf(fullIP, "%s%d", baseIP, i); int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); inet_pton(AF_INET, fullIP, &serverAddr.sin_addr); // 尝试连接 if(connect(sock, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == 0) { NSLog(@"发现相机设备: %s", fullIP); // 此处可添加协议握手验证 } close(sock); } }); } ``` #### 3. **相机协议处理** 检测到设备后需验证是否为相机: ```objective-c // PTP/IP 始化请求(简化版) - (void)verifyCameraAtIP:(NSString *)ip port:(int)port { NSInputStream *inputStream; NSOutputStream *outputStream; [NSStream getStreamsToHost:[NSHost hostWithAddress:ip] port:port inputStream:&inputStream outputStream:&outputStream]; [outputStream open]; uint32_t initPacket = 0x1B; // PTP/IP 始包标识 [outputStream write:(uint8_t *)&initPacket maxLength:sizeof(initPacket)]; // 读取响应(完整实现需处理数据解析) [inputStream open]; uint8_t buffer[1024]; if([inputStream read:buffer maxLength:sizeof(buffer)] > 0) { NSLog(@"确是PTP/IP相机"); } } ``` ### 关键说明 1. **协议支持**: - **PTP/IP**:数码相机标准协议(端口 15740) - **HTTP**:网络摄像头常用协议(端口 80/8080) - **RTSP**:视频流协议(端口 554) 2. **权限要求**: ```xml <key>NSLocalNetworkUsageDescription</key> <string>用于发现网络中的相机设备</string> ``` 3. **制造商SDK**: - 佳能:`Canon EOS SDK` - 索尼:`Camera Remote SDK` - 尼康:`Nikon SDK` ### 注意事项 1. 网络扫描可能触发 iOS 的隐私警告,需在 Info.plist 中声明[^1] 2. Bonjour 搜索需在主线程外执行以避免阻塞 UI 3. 实际生产环境应添加超时处理和错误重试机制 4. 不同相机品牌的协议实现有差异,需参考具体文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值