Objective C Foundation基础框架

[cpp]  view plain copy
  1. <pre name="code" class="cpp">iOS Foundation基础框架就是以Foundation.h头文件的库  
  2. #import <Foundation/Foundation.h>   
  3.   
  4. Mac OS X和iOS都使用了Foundation基础框架。该框架中有很多日后开发常用的API,非常基础重要。以下就常用的类和结构做个介绍。  
  5.   
  6.   
  7. NSObjct  
  8.   
  9. NSObject类,是ObjC类族中的根类。NSObject有一些高级特性支持,在灵活和高效开发中十分常用。  
  10.   
  11. perform…方法和selector  
  12.   
  13. selector是ObjC高级的语法特性,可看作C函数指针,或者Java反射API的Method类相关内容。看一下下面的代码,读者就应该能理解,首先我有个Book类:  
  14.   
  15. #import <Foundation/Foundation.h>  
  16.   
  17. @interface Book : NSObject {  
  18.   
  19. }  
  20.   
  21. -(void) printInformation;  
  22.   
  23. @end  
  24.   
  25. 可以看到有个方法printInformation。一般调用该方法大致是这样:  
  26.   
  27. Book *book=[[Book alloc] init];   
  28. [book printInformation];  
  29.   
  30. 如果使用selector和perform…方法可这样调用:  
  31.   
  32. Book *book=[[Book alloc] init];   
  33. [book printInformation];  
  34.   
  35. SEL method=@selector(printInformation);   
  36. id object=book;   
  37. [object performSelector:method];  
  38.   
  39. 这里,SEL是selector类型。方法可通过这种机制成为变量,传递到任意位置调用,可编写极为灵活和复用性高的代码。  
  40.   
  41. 这里调用的方法没有参数传递,是最简单的情况,下面演示一下带参数的,修改Book类的方法:  
  42.   
  43. #import <Foundation/Foundation.h>  
  44.   
  45. @interface Book : NSObject {  
  46.   
  47. }  
  48.   
  49. -(void) printInformation:(NSString *)bookName;  
  50.   
  51. @end  
  52.   
  53. 带一个参数。那么上面的两种调用方法的代码将修改为:  
  54.   
  55. Book *book=[[Book alloc] init];   
  56. [book printInformation:@"Objective-C Tutorial"];  
  57.   
  58. SEL method=@selector(printInformation:);   
  59. id object=book;   
  60. [object performSelector:method withObject:@"Objective-C Tutorial"];  
  61.   
  62. 如果多个参数呢?比如:  
  63.   
  64. -(void) printInformation:(NSString *)bookName bookPrice:(NSString *)price;  
  65.   
  66.   
  67. 那么:  
  68.   
  69. Book *book=[[Book alloc] init];   
  70. [book printInformation:@"Objective-C Tutorial" bookPrice:@"$17.00"];  
  71.   
  72. SEL method=@selector(printInformation:bookPrice:);   
  73. id object=book;   
  74. [object performSelector:method withObject:@"Objective-C Tutorial" withObject:@"$17.00"];  
  75.   
  76. 再多的参数,直接这样调用就不行了。需要借助NSInvocation类。具体实现就不展开说了。  
  77.   
  78. perform…方法调用还有一个方便的机制,就是延时调用。可以看作一次性的timer。比如:  
  79.   
  80. Book *book=[[Book alloc] init];   
  81. [book printInformation:@"Objective-C Tutorial"];  
  82.   
  83. SEL method=@selector(printInformation:);   
  84. id object=book;   
  85. [object performSelector:method withObject:@"Objective-C Tutorial" afterDelay:10];   
  86. NSLog(@"view did load ok.");  
  87.   
  88. 可以看到多了个参数,afterDelay,参数值单位是秒。结果:  
  89.   
  90. 2011-05-19 15:27:56.930 iOSSimpleDemo[6793:207] Objective-C Tutorial   
  91. 2011-05-19 15:27:56.932 iOSSimpleDemo[6793:207] view did load ok.   
  92. 2011-05-19 15:28:06.931 iOSSimpleDemo[6793:207] Objective-C Tutorial  
  93.   
  94. 从日志可知,带afterDelay参数的方法调用,将延时10秒钟再执行。而主线程并不阻塞,而是继续打印了后面的“view did load ok.”日志。这里的实现原理是,  
  95. 调用afterDelay参数的方法后,将该方法调用存入队列,主线程在10秒后,再从队列中取得它并调用。  
  96.   
  97. 判断对象是否相等  
  98.   
  99. 这里涉及到两个方法:  
  100.   
  101. isEqual  
  102. hash  
  103. 前者,比如:  
  104.   
  105. BOOL isEqual=[book isEqual:book];   
  106. NSLog(@"book is equals: %@",isEqual?@"yes":@"no");  
  107.   
  108. 和Java类似的,相等的对象,它们的hash值必须是相同的。这是因为,hash值将用于依赖hash值的集合元素定位,比如HashSet。hash值不同但相等的对象,  
  109. 将导致在集合中,比如HashSet放入多个。另外,如果自行设置hash值(默认是内存值),不能使用可能变化的值,比如你有个类,User,该类有个属性,name,  
  110. 如果这个name是可改的,就不要用该属性的hash值(字符串的hash值)作为User类的hash方法返回值。  
  111.   
  112.    
  113.   
  114. 获取类对象  
  115.   
  116. 有时候,想知道需要得到Class的类对象,可以调用class方法:  
  117.   
  118. NSLog(@"Book class: %@",[book class]);  
  119.   
  120. 有时候,想要知道超类,可以比如[book superclass]。  
  121.   
  122.    
  123.   
  124. 管理引用计数  
  125.   
  126. 方法比较多:  
  127.   
  128. – retain  required method   
  129. – release  required method   
  130. – autorelease  required method   
  131. – retainCount  required method  
  132.   
  133. 这里不细说了,到内存管理部分会详细讲的。  
  134.   
  135.    
  136.   
  137. 有关对象关系,行为等的测试  
  138.   
  139. 这些方法,在高级开发中常用。比如,判断一个类型是不是属于某个类型:  
  140.   
  141. NSLog(@"book instance is kind of Class Book? %@",   
  142.           [book isKindOfClass:[Book class]]?@"yes":@"no");  
  143.   
  144. 当然子类也是超类类型。比如:  
  145.   
  146. NSLog(@"book instance is kind of Class Book? %@",   
  147.           [book isKindOfClass:[NSObject class]]?@"yes":@"no");  
  148.   
  149. 以上两个语句都会返回yes。  
  150.   
  151. 如果要求严格判断一个实例是不是属于一个类的,可:  
  152.   
  153. NSLog(@"book instance is kind of Class Book? %@",   
  154.           [book isMemberOfClass:[NSObject class]]?@"yes":@"no");  
  155.   
  156.    
  157.   
  158. 这里会返回no,因为book是Book类的实例,而不是严格意义上的NSObject类的实例。  
  159.   
  160. 另外,还有个高级的用法,就是判断实例是不是代理类。即:  
  161.   
  162. - (BOOL)isProxy  
  163.   
  164. 这里先要说说Foundation kit提供的代理类用法,即NSProxy。先写个Book的代理类。头文件:  
  165.   
  166. #import <Foundation/Foundation.h>   
  167. #import "Book.h"  
  168.   
  169. @interface BookProxy : NSProxy {   
  170.     Book *book;   
  171. }  
  172.   
  173. -(id)init;  
  174.   
  175. @property(nonatomic,retain) Book *book;  
  176.   
  177. @end  
  178.   
  179. 实现:  
  180.   
  181. #import "BookProxy.h"  
  182.   
  183. @implementation BookProxy  
  184.   
  185. @synthesize book;  
  186.   
  187. -(id)init{   
  188.     return self;   
  189. }  
  190.   
  191. - (void)forwardInvocation:(NSInvocation *)anInvocation{   
  192.     [anInvocation setTarget:book];   
  193.       
  194.     NSLog(@"call proxy instance …");   
  195.     [anInvocation invoke];   
  196.     NSLog(@"call proxy instance ok.");   
  197.       
  198.     return;   
  199. }  
  200.   
  201. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{   
  202.     return [book methodSignatureForSelector:aSelector];   
  203. }  
  204.   
  205. @end  
  206.   
  207. 调用:  
  208.   
  209. BookProxy *bookProxy=[[BookProxy alloc]init];   
  210. bookProxy.book=book;  
  211.   
  212. book=(Book *)bookProxy;   
  213. [book printInformation:@"Objective-C Tutorial"];  
  214.   
  215. NSLog(@"Book class: %@",[book class]);   
  216. NSLog(@"book instance is kind of Class Book? %@",   
  217.       [book isKindOfClass:[NSObject class]]?@"yes":@"no");  
  218.   
  219. 这里要注意的是,NSProxy类没有init方法(是NSObject类才有),需要自己写一个。从BookProxy到Book要做一次强制转型。之后,使用上就是透明代理了。  
  220. isKindOfClass会返回yes。isMemberOfClass会返回no。但是,怎么区分是子类还是代理类呢?就用到这个了:  
  221.   
  222. - (BOOL)isProxy  
  223.   
  224. 行为,英文是behavior,是动作嘛,一般指的就是方法。有时候,需要判断一个对象,是否能对一个selector做出回应。比如:  
  225.   
  226. SEL method=@selector(printInformation:);   
  227. id object=book;   
  228. [object performSelector:method withObject:@"Objective-C Tutorial" afterDelay:10];   
  229. NSLog(@"view did load ok.");  
  230.   
  231. NSLog(@"book has this selector: %@",[book respondsToSelector:method]?@"yes":@"no");  
  232.   
  233. 这里打印的是yes。  
  234.   
  235. 有的时候,想判断某个实例是否实现了某个协议,可以:  
  236.   
  237. NSLog(@"book implement NSObject protocol: %@",   
  238.          [book conformsToProtocol:@protocol(NSObject)]?@"yes":@"no");  
  239.   
  240. 还有一些方法,可以查看NSObject类reference学习。  
  241.   
  242.    
  243.   
  244. 常用的结构体  
  245.   
  246. 结构体是C提供的一种数据类型。在ObjC中也常使用。比如:  
  247.   
  248. NSRange  
  249. NSPoint  
  250. NSSize  
  251. NSRect  
  252. 以NSRange为例:  
  253.   
  254. typedef struct _NSRange {   
  255.     NSUInteger location;   
  256.     NSUInteger length;   
  257. } NSRange;  
  258.   
  259. 上面代码是从NSRange头文件中找到的。  
  260.   
  261. 可以用三种方式为结构体赋值。比如:  
  262.   
  263. NSRange range;   
  264. range.location=17;   
  265. range.length=4;  
  266.   
  267. 还可以:  
  268.   
  269. NSRange range={17,4};  
  270.   
  271. 或者:  
  272.   
  273. NSRange range=NSMakeRange(17, 4);  
  274.   
  275. 第三种是比较常用的方式,因为是通过函数调用,可在各种情况下使用。  
  276.   
  277. 使用结构体作为数据类型而不是ObjC对象,是从性能上的考虑。后者在动态分配内存上代价较大。  
  278.   
  279.    
  280.   
  281. NSString  
  282.   
  283. NSString类似Java中的String类,提供了很多便利的对字符串操作的方法。字符串操作在开发中是十分常用的。  
  284.   
  285.    
  286.   
  287. 如何创建字符串  
  288.   
  289. 最普通的创建字符串的方式是:  
  290.   
  291. @"hello"  
  292.   
  293. 我测试了一下这个:  
  294.   
  295. NSLog(@"print string hash, instance1: %i, instance2: %i",   
  296.           [@"hello" hash],[@"hello" hash]);  
  297.   
  298. 日志显示:  
  299.   
  300. print string hash, instance1: -1553534663, instance2: -1553534663  
  301.   
  302. 这说明什么呢?两次创建的对象,是内存中同一个实例。这和Java中的String实例化原理是相同的。即系统要保持一个字符串池。当声明的字符串在池中已存在了,  
  303. 就只提供一个指向存在字符串的指针。这也是为什么字符串是不可修改对象的原因之一。  
  304.   
  305. 字符串还提供了stringWithFormat方法创建可插入参数的字符串:  
  306.   
  307. NSString *content=[NSString stringWithFormat:@"用户姓名:%@",@"张三"];  
  308.   
  309. 这里使用的是类方法,而不是实例方法。可以将这个方法看作简单工厂模式。  
  310.   
  311.    
  312.   
  313. 字符串长度  
  314.   
  315. 得到字符串长度,是常见的操作:  
  316.   
  317. unsigned int length=[content length];  
  318.   
  319.    
  320.   
  321. 字符串的相等  
  322.   
  323. 有的时候,需要判断两个NSString字符串是否相等。这里有两个概念:  
  324.   
  325. 对象不一样,但是他们的字符值是一样的  
  326. 对象是同一个,即在内存中同一个区域  
  327. 这个概念在各种面向对象语言中应该都有。我拿Java举例子,比如:  
  328.   
  329. String s="hello";  
  330.   
  331. 这个语义上和:  
  332.   
  333. NSString *s=@"hello";  
  334.   
  335. 是一样的。即查找字符串内存池,看是否有包含相同字符串的对象,如果有,就不重复创建,而是引用池中的字符串对象。因此,用上面语法,  
  336. 用不同变量名创建多个相同字符串的变量,它们字符串值一样,而且,hash值也一样,即在内存中也是同一个对象。  
  337.   
  338. 但是Java如果:  
  339.   
  340. String s=new String("hello");  
  341.   
  342. 就是强制创建新的对象,那么字符串值一样,但是内存上不是同一个对象,因为这样创建不使用字符串池。  
  343.   
  344. 问题来了,ObjC怎么写出这样的语句?我没有找到。应该是有的吧。  
  345.   
  346. 如果在ObjC中判断两个字符串是不是相同的对象,用==即可。如果是判断字符串值是否相等:  
  347.   
  348. NSString *s=@"hello";   
  349. [s isEqualToString:@"hello"];  
  350.   
  351. 建议使用isEqualToString针对字符串值是否相等时使用,而不是==,因为不排除有情况是内存中不是相同对象,但字符串值是相同的情况。  
  352.   
  353.    
  354.   
  355. 字符串的排序  
  356.   
  357. 字符串排序,比如按照首字母排序,两个字符串,比较谁应该排在前面。这时要用到:  
  358.   
  359. - (NSComparisonResult)compare:(NSString *)aString  
  360.   
  361. 比如:  
  362.   
  363. NSString *s1=@"Apple";   
  364. NSString *s2=@"Google";   
  365. NSComparisonResult result=[s1 compare:s2];  
  366.   
  367. switch (result) {   
  368.     case NSOrderedSame:   
  369.         NSLog(@"is same string");   
  370.         break;   
  371.     case NSOrderedAscending:   
  372.         NSLog(@"ascending");   
  373.         break;   
  374.     case NSOrderedDescending:   
  375.         NSLog(@"descending");   
  376.         break;   
  377.     default:   
  378.         break;   
  379. }  
  380.   
  381.    
  382.   
  383. 结果是:  
  384.   
  385. ascending  
  386.   
  387. 也就是说s1和s2之间的顺序是升序,即s1应该排在前面。  
  388.   
  389. 另外,可以使用这个方法:  
  390.   
  391. - (NSComparisonResult)compare:(NSString *)aString options:(NSStringCompareOptions)mask  
  392.   
  393. 进行特殊的大小比较,mask确定特殊比较的类型:  
  394.   
  395. 大小写敏感  
  396. 大小写不敏感  
  397. 数字排序,这个要特别说一下,数字和文字有不同,比如1和9,1排在9前面,无论是字符还是数字都没问题。如果100和99,字符比较就会出现100在99之前的问题  
  398.    
  399.   
  400. 是否包含子字符串  
  401.   
  402. 经常要用到这样的字符串功能,判断字符串:  
  403.   
  404. - (BOOL)hasPrefix:(NSString *)aString,是否某个字符串开始的  
  405. - (BOOL)hasSuffix:(NSString *)aString,是否某个字符串结束的  
  406. - (NSRange)rangeOfString:(NSString *)aString,字符串中是否有子字符串,如果有返回NSRange结构体,包含起始位置和长度,  
  407. 如没有,range.location==NSNotFound  
  408. NSMutableString  
  409.   
  410. 可变字符串。NSString是不可变的,类似Java的String;NSMutableString类似Java的StringBuffer。  
  411.   
  412. 具体方法使用,见Reference。  
  413.   
  414.    
  415.   
  416. 使用集合  
  417.   
  418.    
  419.   
  420. NSArray  
  421.   
  422. NSArray是最常用的集合类型。它类似Java中的ArrayList,但是又有所区别,就是一旦创建就不能再改变。  
  423.   
  424. NSArray有两个限制:  
  425.   
  426. 不能存储C语言的基本数据类型,比如intfloatenumstruct等  
  427. 不能存储nil对象  
  428. 比较常用的创建NSArray实例的方法是:  
  429.   
  430. + (id)arrayWithObjects:(id)firstObj, …  
  431.   
  432. 其他的看Reference吧。  
  433.   
  434. 获取NSArray的元素数:  
  435.   
  436. - (NSUInteger)count  
  437.   
  438. 从指定的位置,比如第2个下标获取元素,要用到这个:  
  439.   
  440. - (id)objectAtIndex:(NSUInteger)index  
  441.   
  442. 结合上面的count方法,可以对NSArray做循环迭代了。  
  443.   
  444.    
  445.   
  446. NSMutableArray  
  447.   
  448. 这个类,允许添加和删除元素。  
  449.   
  450. 添加:  
  451.   
  452. - (void)addObject:(id)anObject  
  453.   
  454. 删除:  
  455.   
  456. - (void)removeObject:(id)anObject  
  457.   
  458. 或者根据下标删除:  
  459.   
  460. - (void)removeObjectAtIndex:(NSUInteger)index  
  461.   
  462.    
  463.   
  464. NSEnumerator  
  465.   
  466. 在Java中有迭代器Iterator,在ObjC中类似功能的类是NSEnumerator。比如:  
  467.   
  468. NSArray *array=[NSArray arrayWithObjects:@"h1",@"h2",nil];   
  469. NSEnumerator *enumerator=[array objectEnumerator];   
  470. NSString *string;   
  471. while (string=[enumerator nextObject]) {   
  472.     NSLog(@"element: %@",string);   
  473. }  
  474.   
  475.    
  476.   
  477. 快速枚举  
  478.   
  479. 很类似Java中的:  
  480.   
  481. for (String s:array) {   
  482.       
  483. }  
  484.   
  485.    
  486.   
  487. ObjC提供了这样的语法支持:  
  488.   
  489. NSArray *array=[NSArray arrayWithObjects:@"h1",@"h2",nil];  
  490.   
  491. for (NSString *string in array) {   
  492.     NSLog(@"element: %@",string);   
  493. }  
  494.   
  495.    
  496.   
  497. NSSet和NSMutableSet  
  498.   
  499. 类似Java中的HashSet。NSSet是不可变的,而NSMutableSet是可变的。使用和NSArray类似。  
  500.   
  501.    
  502.   
  503. NSDictionary和NSMutableDictionary  
  504.   
  505. 类似Java中的HashMap。  
  506.   
  507. 可通过:  
  508.   
  509. - (id)initWithObjectsAndKeys:(id)firstObject , …  
  510.   
  511. 初始化带键值对的NSDictionary。比如:  
  512.   
  513. NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:   
  514.     @"value1", @"key1", @"value2", @"key2", nil];  
  515.   
  516. NSMutableDictionary增加了:  
  517.   
  518. - (void)setObject:(id)anObject forKey:(id)aKey  
  519.   
  520. 可加入新的键值对。和删除键值对:  
  521.   
  522. - (void)removeObjectForKey:(id)aKey  
  523.   
  524.    
  525.   
  526. 各种数值  
  527.   
  528. 上面提到了,C语言的基本数据类型是不能存储到集合里的。需要将这些数据类型封装到对象中才能放入。遗憾的是,ObjC不像Java或者.net,  
  529. 提供了自动装箱和拆箱的功能,即编程语言支持自动将基本型包装成对象,或者相反的操作。ObjC提供了手动的方式。下面介绍一下。  
  530.   
  531. NSNumber  
  532.   
  533. NSNumber提供了很多类似这样的类方法:  
  534.   
  535. + (NSNumber *)numberWithInt:(int)value  
  536.   
  537. 用来将数值型基本数据类型包装成ObjC对象。比如,把int型包装成ObjC的实例:  
  538.   
  539. NSNumber *number=[NSNumber numberWithInt:24];  
  540.   
  541. 这个number已经是ObjC对象了,可以放置到集合中去了。  
  542.   
  543. 反过来:  
  544.   
  545. int n=[number intValue];  
  546.   
  547.    
  548.   
  549. NSValue  
  550.   
  551. NSNumber只能包装数值。NSValue可以包装任意类型数值,比如将结构体包装放入到集合中。  
  552.   
  553. 下面示例将NSRange结构体放入到NSArray中:  
  554.   
  555. NSRange numberRange={10,29};   
  556. NSValue *value=[NSValue valueWithRange:numberRange];   
  557. NSArray *array=[NSArray arrayWithObjects:@"h1",value,nil];  
  558.   
  559. 这里使用的方法valueWithRange,是NSValue为常用结构体提供的便利方法。如果是自己定义的结构体呢?  
  560.   
  561. 比如在头文件中定义了struct:  
  562.   
  563. typedef struct{   
  564.     NSString *name;   
  565.     int rank;   
  566. }User;  
  567.   
  568.    
  569.   
  570. 在代码中创建集合,通过NSValue包装结构体存入集合,并且从集合中取出结构体:  
  571.   
  572. User user={@"张三",2};   
  573. NSValue *userValue=[NSValue valueWithBytes:&user objCType:@encode(User)];   
  574. NSArray *myArray=[NSArray arrayWithObjects:@"h1",userValue,nil];  
  575.   
  576. userValue=[myArray objectAtIndex:1];   
  577. [userValue getValue:&user];   
  578. NSLog(@"用户姓名: %@",user.name);  
  579.   
  580.    
  581.   
  582. NSNull  
  583.   
  584. nil有特殊含义,因此不能在集合中保存。那么,如果需要存入空的内容,怎么办呢?  
  585.   
  586. 见下面代码:  
  587.   
  588. NSRange numberRange={10,29};   
  589. NSValue *value=[NSValue valueWithRange:numberRange];   
  590. NSArray *array=[NSArray arrayWithObjects:[NSNull null],value,nil];  
  591.   
  592. 那么,检查是否为null,可以直接用:  
  593.   
  594. if ([array objectAtIndex:0]==[NSNull null]) {   
  595.     NSLog(@"element is null.");   
  596. }  
  597.   
  598.    
  599.   
  600. NSDate  
  601.   
  602. 在Java里有java.util.Date类,在ObjC中对应的是NSDate。写个最简单的示例:  
  603.   
  604. NSDate *date=[NSDate date];   
  605. NSLog(@"time: %@",date);  
  606.   
  607. 将打印出:  
  608.   
  609. time: 2011-05-26 11:44:37 +0800  
  610.   
  611. date方法将返回表示当前时间的NSDate对象。  
  612.   
  613. 下面的方法:  
  614.   
  615. - (id)initWithTimeIntervalSinceNow:(NSTimeInterval)seconds  
  616.   
  617. 可返回当前时间间隔秒数的日期对象。  
  618.   
  619. 下面的方法:  
  620.   
  621. + (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date  
  622.   
  623. 返回和指定日期对象间隔时间的日期对象。  
  624.   
  625. 下面方法:  
  626.   
  627. - (BOOL)isEqualToDate:(NSDate *)anotherDate  
  628.   
  629. 判断日期是否相等。  
  630.   
  631. 下面方法:  
  632.   
  633. - (NSDate *)earlierDate:(NSDate *)anotherDate  
  634.   
  635. 返回更早的日期对象。  
  636.   
  637. - (NSComparisonResult)compare:(NSDate *)anotherDate  
  638.   
  639. 比较日期大小。类似NSString的compare方法。  
  640.   
  641. - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate  
  642.   
  643. 返回日期之间间隔的秒数。  
  644.   
  645.    
  646.   
  647. NSData  
  648.   
  649. 在C语言中,经常将数据缓冲区作为参数传递给函数。这时需要将缓冲区的指针传递给函数。如果是动态分配的缓冲区,那么还要考虑何时释放内存。  
  650.   
  651. 在ObjC中,可以使用NSData简化缓冲区的使用方式。比如:  
  652.   
  653. char *s="hello everyone";   
  654. NSData *data=[NSData dataWithBytes:s length:strlen(s)+1];   
  655. NSLog(@"data: %s",[data bytes]);  
  656.   
  657. 这里char *s不是动态分配内存的,这里只是演示一下,通过NSData的类方法,可以将s的字节数组复制到NSData中。NSData是ObjC的类实例,有内存管理机制,  
  658. 这里按照ObjC内存管理原则应该是已经autorelease了的。  
  659. </pre><br>  
  660. <br>  
  661. <pre></pre>  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值