NSIndexPath
* 简单了解
是Foundation框架中的一个普通的类,它用来表示一个树形的记录地址。它提供了到嵌套数列的树中特定节点的路径,事实上,它是一个整数阵列,表格视图使用这个去表现在特定分区中的特定行。
注意:
1>问题一: UITableView 中的NSIndexPath属性.Row 和 .section 是通过UITableview中NSIndexPath的分类定义的. 并不是NSIndexPath本身就有的.
2>问题二: 由于分类是不可以添加属性的,只能添加方法,那这里为什么可以呢? ,这是因为它通过runtime.h运行时为分类绑定属性.(示例来源)
NSIndexPath_PageCardView.h
NSIndexPath_PageCardView.m
* 关键点:
1、property需要使用dynamic修饰符,使用dynamic修饰符就需要自己手动来实现get和set方法。
2、get方法通过objc_getAssociatedObject来获取。
3、set方法是通过objc_setAssociatedObject来设定。
objc_getAssociatedObject和objc_setAssociatedObject都需要指定一个固定的地址,这个固定的地址值用来表示属性的key,起到一个常量的作用。
* 深入了解:
* 概述
NSIndexPath 让你精确指定一个树结构 data structure 里面的某个节点的数据。比如你有一个 NSArray, 里面很多节点,每个节点又是一个 NSArray,每个节点的这个里面又是一个NSArray,然后下面又是一个 NSArray,这样简单说起来,你有一个四层的 NSarray ,每层下面都有好多个 NSArray。然后你造一个NSIndexPath 1.3.4.2。你就可以拿它访问,第一层的第三个节点之下的第四个节点的第二个节点的数据。
* 常用方法和属性
* --用Index 或者 index数组和路径的长度 创建NSIndexPath; + (instancetype)indexPathWithIndex:(NSUInteger)index;
+ (instancetype)indexPathWithIndexes:(const NSUInteger [])indexes length:(NSUInteger)length;
- (instancetype)init;
- (instancetype)initWithIndexes:(const NSUInteger [])indexes length:(NSUInteger)length;
* --修改:注意返回的是一个新的对象,不是原来的对象基础上改得。
- (NSIndexPath *)indexPathByAddingIndex:(NSUInteger)index;
- (NSIndexPath *)indexPathByRemovingLastIndex;
* --访问属性、比较(通过Position可以获取到相应的节点的数据)
- (NSUInteger)indexAtPosition:(NSUInteger)position;
- (NSUInteger)length; //路径包含节点个数 或 “路径长度"
* --comparison support
- (NSComparisonResult)compare:(NSIndexPath *)otherObject;
* 示例一 :
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:1];
NSLog(@"%@ length:%D ",indexPath,indexPath.length);
打印结果:
<NSIndexPath: 0x8a0ea20> {length = 1, path = 1} length:1
* 示例二:
indexPath = [indexPath indexPathByAddingIndex:24];
NSLog(@"%@ length:%D ",indexPath,indexPath.length);
NSLog(@"postion:%d",[indexPath indexAtPosition:1]);
打印结果:
<NSIndexPath: 0x8c54090> {length = 2, path = 1 - 24} length:2
postion:24
* 示例三:
NSUInteger indexArr[] ={9,2,3,4};
NSIndexPath * indexPath =[NSIndexPath indexPathWithIndexes:indexArr length:2];
NSLog(@"indexPath.row:%ld",[indexPath indexAtPosition:0]);
打印结果:
indexPath.row:9
NSIndexSet
* NSIndexSet是什么?
* 它代表一个不可变的独特的无符号整数的集合,称为索引,因为使用它们的方式。这个集合被称为索引集。你不应该使用索引集存储任意集合的整数值,因为索引集按索引排序范围的方式存储的。这使得它们更有效率比存储单个整数的集合。这也意味着每个索引值指数中只能出现一次。通俗点讲NSIndexSet就是一个唯一的,有序的,无符号整数的集合。
* NSIndexSet的作用?
* NSIndexSet 用来让你从某个 data structure 里面提取一部分东西出来成为一个新的东西。比如你有一个 NSArray, 里面是(one, two, three, four, five),然后你造了个 indexSet 的内容是 1,2,3,5,然后你把它套到那个 array 上,就是 (one, two,three,five)。* NSIndexSet的一些常用方法。
* 类方法:
初始化
创建一个空的索引集合。
+ (id)indexSet
创建一个索引集合,根据索引值
+ (id)indexSetWithIndex:(NSUInteger)index
创建一个索引集合,根据一个NSRange对象
+ (id)indexSetWithIndexesInRange:(NSRange)indexRange
* 实例方法:
* 初始化 创建一个索引集合,根据一个NSRange对象
- (instancetype)initWithIndexesInRange:(NSRange)range NS_DESIGNATED_INITIALIZER;
创建一个索引集合,根据另一个索引集合
- (instancetype)initWithIndexSet:(NSIndexSet *)indexSet NS_DESIGNATED_INITIALIZER;
创建一个索引集合,根据索引值
- (instancetype)initWithIndex:(NSUInteger)value
* 查询indexsets
- (NSUInteger)indexPassingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate
- (NSIndexSet *)indexesPassingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate
- (NSUInteger)indexWithOptions:(NSEnumerationOptions)optspassingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate
- (NSIndexSet *)indexesWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(NSUIntegeridx, BOOL *stop))predicate
- (NSUInteger)indexInRange:(NSRange)range options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(NSUIntegeridx, BOOL *stop))predicate
- (NSIndexSet *)indexesInRange:(NSRange)range options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(NSUIntegeridx, BOOL *stop))predicate
* 比较
判断两个索引集是否相等
- (BOOL)isEqualToIndexSet:(NSIndexSet *)indexSet;
判断索引集合中是否包含制定的索引值
- (BOOL)containsIndex:(NSUInteger)index
判断索引集合是否包含指定的indexSet
- (BOOL)containsIndexes:(NSIndexSet *)indexSet
判断索引集合是否包含指定的indexRange
- (BOOL)containsIndexesInRange:(NSRange)indexRange
when the index set contains one or more of the indexes in indexRange, NO otherwise(苹果API)
- (BOOL)intersectsIndexesInRange:(NSRange)range
* 获取indexsets
- (NSUInteger)indexLessThanIndex:(NSUInteger)index
- (NSUInteger)indexLessThanOrEqualToIndex:(NSUInteger)index
- (NSUInteger)indexGreaterThanOrEqualToIndex:(NSUInteger)index
- (NSUInteger)indexGreaterThanIndex:(NSUInteger)index
- (NSUInteger)getIndexes:(NSUInteger *)indexBuffer maxCount:(NSUInteger)bufferSize inIndexRange:(NSRangePointer)indexRange
返回indexRange中包含的索引数量
- (NSUInteger)countOfIndexesInRange:(NSRange)indexRange
返回索引集合包含的索引数量
- (NSUInteger)count
* 迭代器遍历
- (void)enumerateRangesInRange:(NSRange)range options:(NSEnumerationOptions)opts usingBlock:(void (^)(NSRangerange, BOOL *stop))block
- (void)enumerateRangesUsingBlock:(void (^)(NSRange range, BOOL *stop))block
- (void)enumerateRangesWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(NSRangerange, BOOL *stop))block
* 迭代Indexes
枚举NSIndexSet;执行Block操作,在指定的Rang范围内,并使用指定的options方法。- (void)enumerateIndexesUsingBlock:(void (^)(NSUInteger idx, BOOL *stop))block
- (void)enumerateIndexesWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(NSUIntegeridx, BOOL *stop))block
- (void)enumerateIndexesInRange:(NSRange)range options:(NSEnumerationOptions)opts usingBlock:(void (^)(NSUInteger idx, BOOL *stop))block
* 如果,要枚举的NSIndexSet中不存在Rang中所指定的范围,则跳过。
* options参数:
enum {
NSEnumerationConcurrent = (1UL << 0),
NSEnumerationReverse = (1UL << 1),
};
* typedef NSUInteger NSEnumerationOptions;
* NSEnumerationConcurrent
枚举过程中,各个Block是同时开始执行的。这样枚举的完成顺序是不确定的。
* NSEnumerationReverse
以反序方式枚举。
* 属性:
@property (readonly) NSUInteger count;
@property (readonly) NSUInteger firstIndex;
@property (readonly) NSUInteger lastIndex;
* NSIndexSet的一些常规用法(部分)
* NSArray中
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes;
- (void)enumerateObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOLBOOL *stop))block;
- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOLBOOL *stop))predicate;<pre name="code" class="objc">......
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes;
- (void)insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes;
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects;
<h4> * UITableView中 </h4>
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
NSMutableIndexSet -可变的索引集 继承于NSIndexSet
- (void)addIndexes:(NSIndexSet *)indexSet;
- (void)removeIndexes:(NSIndexSet *)indexSet;
- (void)removeAllIndexes;
- (void)addIndex:(NSUInteger)value;
- (void)removeIndex:(NSUInteger)value;
- (void)addIndexesInRange:(NSRange)range;
- (void)removeIndexesInRange:(NSRange)range;
- (void)shiftIndexesStartingAtIndex:(NSUInteger)index by:(NSInteger)delta;
NSRange
* NSRange用来表示事物的一个范围,通常是字符串里的字符范围或者数组里的元素范围
* NSRange结构:
typedef struct _NSRange {NSUInteger location;
NSUInteger length;
} NSRange;
NSRange有2个成员
NSUInteger location :表示该范围的起始位置NSUInteger length :表示该范围内的长度
* 创建方法:
NSMakeRange(NSUInteger loc, NSUInteger len) {NSRange r;
r.location = loc;
r.length = len;
return r;
}
* 打印方法:
NSLog(@"Range is: %@", NSStringFromRange(range)NSCharacterSet及NSMutableCharacterSet
NSCharacterSet ,以及它的可变版本NSMutableCharacterSet,
* 了解
用面向对象的方式来表示一组Unicode字符。它经常与NSString及NSScanner组合起来使用,在不同的字符上做过滤、删除或者分割操作。为了给你提供这些字符是哪些字符的直观印象,请看看NSCharacterSet 提供的类方法:
alphanumericCharacterSet
capitalizedLetterCharacterSet
controlCharacterSet
decimalDigitCharacterSet
decomposableCharacterSet
illegalCharacterSet
letterCharacterSet
lowercaseLetterCharacterSet
newlineCharacterSet
nonBaseCharacterSet
punctuationCharacterSet
symbolCharacterSet
uppercaseLetterCharacterSet
whitespaceAndNewlineCharacterSet
whitespaceCharacterSet
* 与它的名字所表述的相反,NSCharacterSet 跟 NSSet 一点关系都没有。
* 虽然底层实现不太一样,但是 NSCharacterSet 在概念上跟 NSIndexSet 还有点相似的。NSIndexSet,之前提到过,表示一个有序的不重复的无符号整数的集合。Unicode字符跟无符号整数类似,大致对应一些拼写表示。所以,一个 NSCharacterSet +lowercaseCharacterSet 字符集与一个包含97到122范围的 NSIndexSet 是等价的。
* 现在我们对理解 NSCharacterSet 的基本概念已经有了少许自信,让我们来看一些它的模式与反模式吧:
* 去掉空格
* NSString -stringByTrimmingCharactersInSet: 是个你需要牢牢记住的方法。它经常会传入 NSCharacterSet +whitespaceCharacterSet 或 +whitespaceAndNewlineCharacterSet 来删除输入字符串的头尾的空白符号。* 需要重点注意的是,这个方法 仅仅 去除了 开头 和 结尾 的指定字符集中连续字符。这就是说,如果你想去除单词之间的额外空格,请看下一步。
* 挤压空格
* 假设你去掉字符串两端的多余空格之后,还想去除单词之间的多余空格,这里有个非常简便的方法: NSString *string = @"Lorem ipsum dolar sit amet.";
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *components = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
components = [components filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self <> ''"]];
string = [components componentsJoinedByString:@" "];
首先,删除字符串首尾的空格;然后用
NSString -
componentsSeparatedByCharactersInSet: 在空格处将字符串分割成一个 NSArray;再用一个 NSPredicate 去除空串;最后,用 NSArray -componentsJoinedByString: 用单个空格符将数组重新拼成字符串。注意:这种方法仅适用于英语这种用空格分割的语言。
* 字符串分词
* 不要用 NSCharacterSet 来分词。 用 CFStringTokenizer 来替代它。* 你用 componentsSeparatedByCharactersInSet: 来清理用户输入是可以谅解的,但是用它来做更复杂的事情,你将陷入痛苦的深渊。
* 为什么?请记住,语言并不是都用空格作为词的分界。虽然实际上以空格分界的语言使用非常广泛。但哪怕只算上中国和日本就已经有十多亿人,占了世界人口总量的 16%。
……即使是用空格分隔的语言,分词也有一些模棱两可的边界条件,特别是复合词汇和标点符号。
以上只为说明:如果你想将字符串分成有意义的单词,那么请用 CFStringTokenizer (或者 enumerateSubstringsInRange:options:usingBlock:)吧。
* 从字符串解析数据
NSScanner 是个用以解析任意或半结构化的字符串的数据的类。当你为一个字符串创建一个扫描器时,你可以指定忽略哪些字符,这样可以避免那些字符以各种各样的方式被包含到解析出来的结果中。* NSCharacterSet 是基础类库中字符串处理系统中的一员,可能是最容易被用错或是误解的一员。在脑中记住这些模式与反模式,你将不仅能做一些很有用的诸如管理空格及从字符串中读信息之类的事情,更重要的是,你将避免误入歧途。
参考:点这里