概述

从前面的博文我们也可以看到,数组和字典中只能存储对象类型,其他基本类型和结构体是没有办法放到数组和字典中的,当然你也是无法给它们发送消息的也就是说有些NSObject的方法是无法调用的,这个时候通常会用到装箱boxing和拆箱unboxing。

其实各种高级语言基本上都有装箱和拆 箱的过程,例如C#中我们将基本数据类型转化为Object就是一个装箱的过程,将这个Object对象转换为基 本数据类型的过程就是拆箱,而且在C#中装箱的过程可以自动完成,基本数据类型可以直接赋值给Object 对象。但是在ObjC中装箱的过程必须手动实现,ObjC不支持自动装箱。

对象的装箱和拆箱 
在ObjC中我们一般将基本数据类型装箱成NSNumber类型当然它也是NSObject的子类,但是NSNumber不能对结构体装箱,调用其对应的方法进行转换:

  1. +(NSNumber *)numberWithChar:(char)value;
  2. +(NSNumber *)numberWithInt:(int)value;
  3. +(NSNumber *)numberWithFloat:(float)value;
  4. +(NSNumber *)numberWithDouble:(double)value;
  5. +(NSNumber *)numberWithBool:(BOOL)value;
  6. +(NSNumber *)numberWithInteger:(NSInteger)value;

拆箱的过程就更加简单了,可以调用如下方法:

  1. -(char)charValue;
  2. -(int)intValue;
  3. -(float)floatValue;
  4. -(double)doubleValue;
  5. -(BOOL)boolValue;
  6. 示例
  1. #import <Foundation/Foundation.h>
  2. /*可以存放基本类型到数组、字典*/
  3. void test1() {
  4. //包装类NSNumber,可以包装基本类型但是无法包装结构体类型
  5. NSNumber *number1 = [NSNumber numberWithChar:'a'];//'a'是一个C语言的char类型我们无 法放倒NSArray中,但是我们可以通过NSNumber包装
  6. NSArray *array1 = [NSArray arrayWithObject:number1];
  7. NSLog(@"%@", array1);
  8. /*结果:
  9. (
  10. 97
  11. ) */
  12. NSNumber *number2 = [array1 lastObject];
  13. NSLog(@"%@", number2);//返回的不是基本类型,结果:97
  14. char char1 = [number2 charValue];//number转化为char
  15. NSLog(@"%c", char1); //结果:a
  16. }
  17. int main(int argc, const char *argv[]) {
  18. @autoreleasepool {
  19. test1();
  20. }
  21. return 0;
  22. }

结构体的装箱和拆箱 
上面我们看到了基本数据类型的装箱和拆箱过程,那么结构体呢?

这个时候我们需要引入另外一个类型NSValue,其实上面的NSNumber就是NSValue的子类,它包装了一些基本数据类型的常用装箱、拆箱方法,当要对结构体进行装箱、拆箱操作我们需要使用NSValue,NSValue可以对任何数据类型进行装箱、拆箱操作。

事实上对于常用的结构体Foundation已经为我们提供好了具体的装箱方法:

  1. +(NSValue *)valueWithPoint:(NSPoint)point;
  2. +(NSValue *)valueWithSize:(NSSize)size;
  3. +(NSValue *)valueWithRect:(NSRect)rect;

对应的拆箱方法:

  1. -(NSPoint)pointValue;
  2. -(NSSize)sizeValue;
  3. -(NSRect)rectValue;
  4. 示例
  1. #import <Foundation/Foundation.h>
  2. //NSNumber是NSValue的子类,而NSValue可以包装任何类型,包括结构体
  3. void test1() {
  4. CGPoint point1 = CGPointMake(10, 20);
  5. NSValue *value1 = [NSValue valueWithPoint:point1];//对于系统自带类型一般都有直接的方 法进行包装
  6. NSArray *array1 = [NSArray arrayWithObject:value1];//放倒数组中
  7. NSLog(@"%@",array1);
  8. /*结果:
  9. (
  10. "NSPoint: {10, 20}"
  11. ) */
  12. NSValue *value2 = [array1 lastObject];
  13. CGPoint point2 = [value2 pointValue];//同样对于系统自带的结构体有对应的取值方法(例如 本例pointValue)
  14. NSLog(@"x=%f,y=%f", point2.x, point2.y);//结果:x=10.000000,y=20.000000
  15. }
  16. int main(int argc, const char *argv[]) {
  17. @autoreleasepool {
  18. test1();
  19. }
  20. return 0;
  21. }

自定义的结构体类型的装箱和拆箱 
如果是我们自定义的结构体类型呢,这个时候我们需要使用NSValue如下方法进行装箱:

  1. +(NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;

调用下面的方法进行拆箱:

  1. -(void)getValue:(void *)value;

示例

  1. #import <Foundation/Foundation.h>
  2. typedef struct {
  3. int year;
  4. int month;
  5. int day;
  6. } Date;
  7. //NSNumber是NSValue的子类,而NSValue可以包装任何类型,包括结构体
  8. void test1() {
  9. //如果我们自己定义的结构体包装
  10. Date date = {2014, 2, 28};
  11. char *type = @encode(Date);
  12. NSValue *value3 = [NSValue value:&date withObjCType:type];//第一参数传递结构体地址,第二个参数传递类型字符串
  13. NSArray *array2 = [NSArray arrayWithObject:value3];
  14. NSLog(@"%@", array2);
  15. /*结果:
  16. (
  17. "<de070000 02000000 1c000000>"
  18. ) */
  19. Date date2;
  20. [value3 getValue:&date2];//取出对应的结构体,注意没有返回值
  21. //[value3 objCType]//取出包装内容的类型 NSLog(@"%i,%i,%i",date2.year,date2.month,date2.day); //结果:2014,2,28
  22. }
  23. int main(int argc, const char *argv[]) {
  24. @autoreleasepool {
  25. test1();
  26. }
  27. return 0;
  28. }

Objective-C(装箱和拆箱)的更多相关文章

  1. C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱

    一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...

  2. 【译】.NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

  3. Java暗箱操作之自动装箱与拆箱

    我以前在写Android项目的时候,估计写得最多最熟练的几句话就是: List<Integer> list = new ArrayList<Integer>(); list.a ...

  4. java 自动装箱自动拆箱

    1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...

  5. Java 自动装箱与拆箱

    Java 自动装箱与拆箱(Autoboxing and unboxing)   什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供 ...

  6. .NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱 (转)

    作者: Edison Chou  来源: 博客园  发布时间: 2014-09-03 15:59  阅读: 318 次  推荐: 2   原文链接   [收藏]   原文作者:Shivprasad k ...

  7. .NET中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

  8. 深入剖析Java中的装箱和拆箱

    深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...

  9. 转 C# 装箱和拆箱[整理]

    1.      装箱和拆箱是一个抽象的概念 2.      装箱是将值类型转换为引用类型 :拆箱是将引用类型转换为值类型       利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的 ...

  10. 《Java中的自动装箱和拆箱功能.》

    //Java中的自动装箱和拆箱功能. class AutoboxingUnboxing { public static void main(String[] args) { //直接把一个基本类型变量 ...

随机推荐

  1. Notepad++编译和运行Java

    首先要让Notepad++编译和运行Java,前提是电脑里已经配置好了Java的环境(这里可以参考我博客里关于Java环境配置的那篇随笔). 在Notepad++上面的选项栏中找到 插件---> ...

  2. Win32 进程间通信的分析与比较

    1 进程与进程通信 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源(如文件.管道等)组成.多进程/多线 程是Windows操作系统的一个基本特征.M ...

  3. python基础学习-思维导图总结

  4. python 爬虫系列07-天气爬虫

    看天气 import requests from bs4 import BeautifulSoup ALL_DATA = [] def parse_page(url): headers = { 'Us ...

  5. 如何实现一个简单的MVVM框架

    接触过web开发的同学想必都接触过MVVM,业界著名的MVVM框架就有AngelaJS.今天闲来无事,决定自己实现一个简单的MVVM框架玩一玩.所谓简单,就是仅仅实现一个骨架,仅表其意,不摹其形. 分 ...

  6. Nginx使用的php-fpm的两种进程管理方式及优化

    PS:前段时间配置php-fpm的时候,无意中发现原来它还有两种进程管理方式.与Apache类似,它的进程数也是可以根据设置分为动态和静态的. php-fpm目前主要又两个分支,分别对应于php-5. ...

  7. word 摘要

    word 使用心得 定义快捷键 Tools -> Customize keyboard 自定义快捷键 cmd + L, 左对齐; cmd + R, 右对齐; cmd + E, 居中对齐 cmd ...

  8. [转]微信小程序开发(二)图片上传+服务端接收

    本文转自:http://blog.csdn.net/sk719887916/article/details/54312573 文/YXJ 地址:http://blog.csdn.net/sk71988 ...

  9. JavaScript数组常用操作总结

    我们在日常开发过程中,使用到原生 JavaScript的时候,有时候会频繁的对数组进行操作,今天我把工作以来,经常用到的有关 JavaScript数组的方法总结一下,方便日后工作的时候查找使用! 一. ...

  10. Spring注解之Controller中获取请求参数及验证使用

    1.处理request的uri部分的参数:@PathVariable. 2.处理request header部分的参数:@RequestHeader,@CookieValue@RequestHeade ...