# NSRange 设计之美



> typedef struct _NSRange {
    NSUInteger location;
    NSUInteger length;
} NSRange;

1、看到官方文档的源代码就知道 NSRange 是个结构体，但是如果是你设计一个这样的数据类型你会怎么办？？

设计成结构体，然后有些属性怎么办？比如为了开发者方便，让你设计出一个办法，让开发者可以很快知道这个结构体的上限是什么？

苹果就很机智，设计了一个内联函数

 ```
 NS_INLINE NSUInteger NSMaxRange(NSRange range) {
    return (range.location + range.length);
}
 ```
 
 2、什么是内联函数？
 
 ```
NS_INLINE 返回值类型 函数名(参数列表) {
    //函数实现
    //return ;
}
 ```
 
3、内联函数的应用

比如自定义一个弹窗

```
NS_INLINE void tipWithMessage(NSString *message){
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil];
        
        [alerView show];
        
        [alerView performSelector:@selector(dismissWithClickedButtonIndex:animated:) withObject:@[@0, @1] afterDelay:0.9];
        
    });
    
}

```


4、内联函数的注意事项

内联函数是以代码膨胀为代价， 仅仅省去了函数调用的开销，从而提高函数的执行效率。如果执行函数内代码的时间相比于函数调用的开销大，那么效率收获会很小。
此外每一处调用内联函数的地方都会复制一遍代码，所以会使得程序的体积变大，消耗更多的代码段区域。
所以下面的情况不适合使用内联函数：

    * 如果函数体内的代码比较长，使用内联将导致内存消耗比较大
    * 如果函数体内出现循环，那么执行函数体内代码的时间要比函数的调用开销大
    
    
5、FOUNDATION_EXPORT

查看 NSRange 的代码还会发现一个关键词 **FOUNDATION_EXPORT**，它可以用作定义常量。


FOUNDATION_EXPORT 和 #define 都可用来定义常量。
用法

```
//.h
FOUNDATION_EXPORT NSString *const NickName;

//.m
NSString *const NickName = @"杭城小刘";
```

那么它和 **#define** 　有何区别？

FOUNDATION_EXPORT 在检测字符串的值是否相等的时候效率更高
使用** NickName == MyName** 来判断，而 #define 是用 **[NickName isEqualToString:MyName]** 来判断。


    * 本质上 FOUNDATION_EXPORT 是比较指针的自己
    * \#define 是比较每个字符串是否相等