前言

做iOS开发有3年了,从当初的小白到现在,断断续续看过很多资料,之前也写过一些博文来记录,但是感觉知识点都比较凌乱。所以最近准备抽时间把iOS开发的相关知识进行一个梳理,主要分为OC基础、UI控件、多线程、动画、网络、数据持久化、自动布局、第三方框架等几个模块进行梳理。本系列的所有博文集合参见:iOS开发知识梳理博文集。本文主要介绍 OC基础--数据类型与表达式。

一 数据类型

Objective-C是在C语言基础上拓展出的新语言,所以它是完全兼容C语言代码的,C语言中的基本数据类型如int、float、double和char在Objective-C中是完全可以正常使用的。除此之外,Objective-C还拓展了一些新的数据类型如BOOL、id、instancetype等。

1.1 基本数据类型

因为Objective-C是在C语言基础上拓展出的新语言,所以它是完全兼容C语言代码的,C语言中的基本数据类型都可以正常使用,直接来自C语言中的数据类型如下所示。当然,这些数据类型我们在实际开发过程中很少用到(枚举类型有时候会用到)。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
char ch = 'a'; //字符型
short sh = ; //短整型
int i8 = ; //整型 八进制
int i10 = ; //整型 十进制
int i16 = 0x15; //整型 十六进制
//输出结果: i8 = 13, i10 = 15 i16 = 21
NSLog(@"i8 = %d, i10 = %d i16 = %d", i8, i10, i16);
long l = 6l; //长整型
float f = 3.4f; //单精度浮点型
double d = 5.6; //双精度浮点型//枚举类型
enum EnumDemo {
Spring, //默认为0,后面依次自增
Summer,
Autumn = , //可以指定整数,后面的在这个基础上自增
Winter
}; //结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员
//结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙)
struct StructDemo {
NSString *name;
int length;
}; //共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,共用体的所有成员占用同一段内存,同一时刻只能保存一个成员的值,修改一个成员会影响其余所有成员。
union UnionDemo {
int n;
char ch;
double f;
}; }
return ;
}

1.1.1 不同数据类型的占用存储空间

不同的数据类型占用的存储空间不同,同一数据类型在不同编译器环境下占用的存储空间也不一样。各数据类型占用的存储空间如下表所示。

数据类型 16位编译器 32位编译器 64位编译器
char 1byte 1byte 1byte
int 2byte 4byte 4byte
float 4byte 4byte 4byte
double 8byte 8byte 8byte
short int 2byte 2byte 2byte
unsigned int 2byte 4byte 4byte
long 4byte 4byte 8byte
unsigned long 4byte 4byte 8byte
long long 8byte 8byte 8byte

1.1.2 不同数据类型的输出格式

不同数据类型在打印时,我们需要按照指定的格式进行输出,在OC中NSLog输出格式如下表所示。

格式字符 说明 格式字符 说明

d

带符号十进制 f 小数形式输出,默认输出6位小数
o 无符号八进制 e 指数形式输出,数值不分默认输出6位小数
x 无符号十六进制 g 自动选用%f或%e输出,保证以最简形式输出,并不会输出无意义的0
u 无符号十进制 p 以十六尽职形式输出指针变量所代表的地址值
s 输出C风格字符串 l 用在d、o、x、u之前用于输出长整型;在f、e、g之前用于输出长浮点型
m 用于制定输出数据所占的最小宽度为m位 .n 对于浮点数,表示输出n位小数,对于字符串,表示截取的字符个数
_ 表述输出的数值向左边对齐    

1.2 OC封装的数据类型

除了上面的基本数据类型之外,Objective-C还拓展了一些新的数据类型如BOOL、NSInteger、NSString、CGFloat、id、instancetype等。此外,还有NSNumber、NSValue、NSData等封装类型,有NSDictionary、NSArray、NSSet等集合数据类型,有CGRect/NSRect、CGPoint/NSPoint、CGSize/NSSize等尺寸相关的 ,还有NSRange、NSIndex等范围相关。

1.2.1 BOOL/Boolean

Objective-C中的BOOL类型在不同的架构系统上是不一样的,所以在64-bit架构系统下BOOL是对应C语言中的bool,值只能是1(YES)和0(NO),32-bit架构下是无符号字符型。下面是OC中对BOOL的定义 :

#if defined(__OBJC_BOOL_IS_BOOL)
// Honor __OBJC_BOOL_IS_BOOL when available.
# if __OBJC_BOOL_IS_BOOL
# define OBJC_BOOL_IS_BOOL
# else
# define OBJC_BOOL_IS_BOOL
# endif
#else
// __OBJC_BOOL_IS_BOOL not set.
# if TARGET_OS_OSX || TARGET_OS_MACCATALYST || ((TARGET_OS_IOS || ) && !__LP64__ && !__ARM_ARCH_7K)
//非64-bit架构或非__ARM_ARCH_7K
# define OBJC_BOOL_IS_BOOL
# else
//64-bit架构并且__ARM_ARCH_7K
# define OBJC_BOOL_IS_BOOL
# endif
#endif //所以在64-bit架构系统下BOOL是对应C语言中的bool,否则是无符号字符型
#if OBJC_BOOL_IS_BOOL
typedef bool BOOL;
#else
# define OBJC_BOOL_IS_CHAR
typedef signed char BOOL;
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C"
// even if -funsigned-char is used.
#endif #define OBJC_BOOL_DEFINED #if __has_feature(objc_bool)
#define YES __objc_yes
#define NO __objc_no
#else
#define YES ((BOOL)1)
#define NO ((BOOL)0)
#endif
//用iPhone5和iPhone8模拟器做个实验

BOOL isOK = ;
NSLog(@"%d", isOK); // iPhone5的打印结果 23
// iPhone8的打印结果 1

Objective-C中的Boolean类型其实就是一个无符号字符型。

/********************************************************************************

    Boolean types and values

        Boolean         Mac OS historic type, sizeof(Boolean)==1
bool Defined in stdbool.h, ISO C/C++ standard type
false Now defined in stdbool.h
true Now defined in stdbool.h *********************************************************************************/
typedef unsigned char Boolean;

1.2.2 NSInteger

OC中的NSInteger就是对整型的一个封装,64-bit系统上NSInteger对应的是长整形,32-bit系统上对应的是整型。具体我们可以看OC中的源码的定义:

//64-bit系统上NSInteger对应的是长整形,32-bit系统上对应的是整型
#if __LP64__ || 0 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

1.2.3 数值封装类型 NSNumber、NSValue、NSData

我们在编码中,很多时候需要将C里面原生的数据 (通常是一些结构体) 封装成对象,这样可以用NSDictionary或者NSArray来存取访问。尤其是一些做适配的情况下,这种封装是不可避免的。Objective-C提供了不少类可以帮助我们,比较常见的是NSNumber,NSValue和NSData。

NSValue主要就是将这些原生的数据封装成对象,方便我们进行存储访问。NSValue主要用来封装自定义的数据结构,可以是系统框架提供的CGRect/CGPoint/CGSize等数据结构,也可以是自己定义的struct。

//封装
+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type; //解封
- (void)getValue:(void *)value;
//此外还提供了对基本的尺寸范围相关的封装和解封
+ (NSValue *)valueWithPoint:(NSPoint)point;
+ (NSValue *)valueWithSize:(NSSize)size;
+ (NSValue *)valueWithRect:(NSRect)rect;
+ (NSValue *)valueWithEdgeInsets:(NSEdgeInsets)insets API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0)); @property (readonly) NSPoint pointValue;
@property (readonly) NSSize sizeValue;
@property (readonly) NSRect rectValue;
@property (readonly) NSEdgeInsets edgeInsetsValue API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

使用NSValue对NSPoint进行封装、解封的示例代码如下。

NSPoint point = NSPointFromCGPoint(CGPointMake(, ));
// NSDictionary *dic = @{@"point" : point}; //报错,字典中必须是对象 //通过转化为NSValue进行保存
NSValue *value = [NSValue valueWithPoint:point];
NSDictionary *dic = @{@"point" : value};
//从字典中获取NSValue,并从该对象中获取对应的NSPoint值
NSValue *vv = dic[@"point"];
NSPoint pp = [vv pointValue];
NSLog(@"%@", NSStringFromPoint(pp));

使用NSValue对自定义结构体进行封装和解封的示例代码如下。

//结构体定义
typedef struct StructDemo {
NSString *name;
int age;
} StructDemoTag; //数据创建
StructDemoTag stDemo = {@"zhangsan", }; //封装
NSValue *vv2 = [NSValue value:&stDemo withObjCType:@encode(StructDemoTag)]; NSDictionary *dic2 = @{@"struct_demo" : vv2}; //解封
NSValue *vv3 = dic2[@"struct_demo"];
StructDemoTag stDemo2 = {};
[vv3 getValue:&stDemo2]; NSLog(@"name: %@, age: %d", stDemo2.name, stDemo2.age);
//name: zhangsan, age: 12

NSNumber继承自NSValue,主要是用来封装ANSI C内置的数据,比如char,float,int等等。这个类提供了一些封装/解封的方法,这个使用方法很简单,就不展示了。

//封装方法
+ (NSNumber *)numberWithChar:(char)value;
+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
+ (NSNumber *)numberWithShort:(short)value;
+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
+ (NSNumber *)numberWithInt:(int)value;
+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
+ (NSNumber *)numberWithLong:(long)value;
+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; //解封方法
- (char)charValue;
- (unsigned char)unsignedCharValue;
- (short)shortValue;
- (unsigned short)unsignedShortValue;
- (int)intValue;
- (unsigned int)unsignedIntValue;
- (long)longValue;
- (unsigned long)unsignedLongValue;

NSData主要是提供一块原始数据的封装,将一些图片、文件、字符串等数据转化为字节流数据,方便数据的封装和流动,比较常见的是NSString/NSImage以及文件数据的封装与传递。在应用中,最常用于访问存储在文件中或者网络资源中的数据。一般解封方法在图片UIImage、字符串NSString中有对应的从NSData数据创建。

//以下类方法全部都有成员方法的实现和接口,这里不一一展示

//直接从data封装
+ (instancetype)dataWithData:(NSData *)data; //指定长度的封装
+ (instancetype)dataWithBytes:(nullable const void *)bytes length:(NSUInteger)length; //封装文件对应的
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path;
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr; //封装url对应的
+ (nullable instancetype)dataWithContentsOfURL:(NSURL *)url;
+ (nullable instancetype)dataWithContentsOfURL:(NSURL *)url options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;

NSData在字符串中的使用示例代码如下:

NSString *str = @"hello object-c";
//封装
NSData *data = [NSData dataWithBytes:[str UTF8String] length:str.length];
//解封
NSString *str2 = [NSString stringWithUTF8String:[data bytes]];
NSLog(@"str:%@", str2);

1.2.4 字符串NSString/NSMutableString

字符串内容比较多,我们后面单独写一篇,到时候链接补上来。

1.2.5 集合数据类型

OC中的集合框架主要就是数组(NSArray / NSMutableArray、字典(NSDictionry / NSMutableDictionry)、集合(NSSet / NSMutableSet)。这一部分内容也比较多,我们后面也会单独补充一篇,到时候链接补上来。

1.2.6 尺寸、范围相关的类型

Object-C中有CGRect/NSRect、CGPoint/NSPoint、CGSize/NSSize等尺寸相关的,其实CG开头的和NS开头的都是一个东西,都是struct定义的尺寸相关的结构体,只是定义在不同的框架中。

/* Points. */
struct CGPoint {
CGFloat x;
CGFloat y;
};
typedef struct CG_BOXABLE CGPoint CGPoint; //NSPoint就是CGPoint
typedef CGPoint NSPoint; /* Sizes. */ struct CGSize {
CGFloat width;
CGFloat height;
};
typedef struct CG_BOXABLE CGSize CGSize; //NSSize就是CGSize
typedef CGSize NSSize; /* Rectangles. */
struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CG_BOXABLE CGRect CGRect; //NSRect就是CGRect
typedef CGRect NSRect;
CGRect rect = CGRectMake(, , , );
NSRect rect2 = NSRectFromCGRect(rect); CGPoint point = CGPointMake(, );
NSPoint point2 = NSPointFromCGPoint(point); CGSize size = CGSizeMake(, );
NSSize size2 = NSSizeFromCGSize(size); NSRange range = NSMakeRange(, );

各种尺寸相关的结构体类型数据在OC中打印该如何打印呢?我们需要将结构体类型转为字符串进行打印,系统提供了相应的方法。示例代码如下。

CGRect rect = CGRectMake(, , , );
NSRect rect2 = NSRectFromCGRect(rect);
NSLog(@"%@", NSStringFromRect(rect)); CGPoint point = CGPointMake(, );
NSPoint point2 = NSPointFromCGPoint(point);
NSLog(@"%@", NSStringFromPoint(point)); CGSize size = CGSizeMake(, );
NSSize size2 = NSSizeFromCGSize(size);
NSLog(@"%@", NSStringFromSize(size)); NSRange range = NSMakeRange(, );
NSLog(@"%@", NSStringFromRange(range));

OC基础--数据类型与表达式的更多相关文章

  1. JavaScript的基础数据类型和表达式

    Java Script的基础数据类型和表达式 基本的数据类型: number(数值)类型:可分为整数和浮点数 string(字符)类型:是用单引号“'”或者双引号“"”来说明的. boole ...

  2. OC基础数据类型-NSNumber

    1.NSNumber:专门用来装基础类型的对象,把整型.单精度.双精度.字符型等基础类型存储为对象 //基本数据类型 //专门用来装基础类型的对象 NSNumber * intNumber = [[N ...

  3. OC基础数据类型-NSString

    1.字符串的初始化 //字符串的初始化 NSString *str = @"Hello world!"; NSString *str2 = [[NSString alloc] in ...

  4. OC基础数据类型-NSData-NSMutableData-NSString

    NSData和NSMutableData存储的是二进制数据,在文件操作,网络,以及核心图形图像中使用较广泛.NSData创建后不可以再修改,NSMutableData可以再次修改. 1.NSStrin ...

  5. OC基础数据类型-NSSet

    1.集合:集合(NSSet)和数组(NSArray)有相似之处,都是存储不同的对象的地址:不过NSArray是有序的集合,NSSet是无序的集合.集合是一种哈希表,运用散列算法,查找集合中的元素比数组 ...

  6. OC基础数据类型-NSData

    1.NSData,数据,当我们需要把一些信息写入到文件里或发送到网络上,我们需要把这些数据转换下,变成纯粹的0.1字符流 1 NSString * str = @"hello, world! ...

  7. 【转】 OC基础数据类型-NSSet

    原文 : http://www.cnblogs.com/GISerYang/p/3340937.html 1.集合:集合(NSSet)和数组(NSArray)有相似之处,都是存储不同的对象的地址:不过 ...

  8. OC基础数据类型-NSValue

    1.NSValue:将指针等复杂的类型存储为对象 struct sct { int a; int b; }sctt; NSValue * value = [[NSValue alloc] initWi ...

  9. OC基础数据类型-NSDictionary

    1.字典NSDictionary 字典与数组的区别:数组讲究顺序,而字典可以快速帮助我们找到数据,数据是我们的目的,键是我们的手段 NSDictionary *dict = [[NSDictionar ...

随机推荐

  1. 如何在Spring异步调用中传递上下文

    以下文章来源于aoho求索 ,作者aoho 1. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步 ...

  2. 【CSP2019】括号树 题解(递推+链表)

    前言:抽时间做了做这道题,把学长送退役的题. ----------------- 题目链接 题目大意:定义$()$是合法括号串.如果$A,B$是合法括号串,那么$(AB),AB$为合法括号串.现给定根 ...

  3. cocos2d-x_下载游戏引擎并创建第一个项目

    我是一名小白. 下载并创建游戏项目 第一步:去官网下载cocos2d-x http://www.cocos.com/download 第二步:将安装包里边的 setup.py 拖进命令行点击回车键 , ...

  4. Python datetime 转 JSON

    Python datetime 转 JSON Python 中将 datetime 转换为 JSON 类型,在使用 Django 时遇到的问题. 环境: Python2.7 代码: import js ...

  5. 《RabbitMQ》什么是死信队列

    一 什么是死信队列 当一条消息在队列中出现以下三种情况的时候,该消息就会变成一条死信. 消息被拒绝(basic.reject / basic.nack),并且requeue = false 消息TTL ...

  6. 01-java实现动态数组

    01-手撸动态数组 本篇是恋上数据结构第一季个人总结 借鉴https://juejin.im/post/6844904001478066183#heading-0 本人git https://gith ...

  7. C#LeetCode刷题-图

    图篇 # 题名 刷题 通过率 难度 133 克隆图   18.7% 中等 207 课程表   40.0% 中等 210 课程表 II   40.0% 中等 310 最小高度树   29.5% 中等 3 ...

  8. C#LeetCode刷题之#7-反转整数(Reverse Integer)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3838 访问. 给定一个 32 位有符号整数,将整数中的数字进行反 ...

  9. 使用Python Openssl库解析X509证书信息

    X.509 证书结构描述 常见的X.509证书格式包括: 后缀 作用 cer/crt 用于存放证书,它是2进制形式存放的,不含私钥 pem 以Ascii来表示,可以用于存放证书或私钥. pfx/p12 ...

  10. 【ASP.NET Core学习】使用JWT认证授权

    概述 认证授权是很多系统的基本功能 , 在以前PC的时代 , 通常是基于cookies-session这样的方式实现认证授权 , 在那个时候通常系统的用户量都不会很大, 所以这种方式也一直很好运行, ...