首页 > 娱乐前沿 > 热点
iOS用三种途径实现一方法有多个返回值
佚名 2016-02-15 18:10:27

以前觉得这种标题有点偏向于理论,实际开发中怎么会有这种诡异的需求,但是真正遇到了这种硬需求时觉得还是有那么点价值的,理论付诸了实践在此也就做了个整理。

以我私下开发中的一处代码为例,本意是希望有这么一个方法:能够传入一个开始标记(NSString*)一个结束标记(NSString*)一段文字(NSString*) 然后内部在文字中扫描并返回标记包裹内容的范围(NSRange这个范围是忽视标记的)这个范围可能会有多个所以返回的应该是一个装着range的数组。并且顺便把原来字符串中的开始和结束标记全过滤掉,把过滤后的字符串也返回出来。

举个例子就是:传入开始标记“<” 结束标记“>”一段文字 “会议需要叫上<彼得>和<罗宾>” 然后希望返回一个数组 [{location:6,length:2},{location:9,length:2}] ,和返回处理后的字符串“会议需要叫上彼得和罗宾”。

代码希望能够写成这样,但是是不可能的。

-(NSArray*,NSMutableString*)scanBeginStr:(NSString*)beginstrendStr:(NSString*)endstrinText:(NSMutableString*)text

好下面提供三种途径完成此需求。  

1.使用字典

这种方法是最low但是最容易理解的,就是如果你需要返回多个对象,直接将多个对象塞在一个字典里面自己设置合理的key并返回字典,字典里面可以放任意数量的“返回值”。

-(NSDictionary*)scanBeginStr:(NSString*)beginstrendStr:(NSString*)endstrinText:(NSMutableString*)text{
NSRangerange1,range2;
NSUIntegerlocation=0,length=0;
range1.location=0;
NSMutableArray*rangeArray=[NSMutableArrayarray];
while(range1.location!=NSNotFound){
range1=[textrangeOfString:beginstr];
range2=[textrangeOfString:endstr];
if(range1.location!=NSNotFound){
location=range1.location;
length=range2.location-range1.location-1;
if(length>5000)break;
[textreplaceOccurrencesOfString:beginstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range1.location+range1.length)];
[textreplaceOccurrencesOfString:endstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range2.location+range2.length-1)];
}
[rangeArrayaddObject:@{@"location":@(location),@"length":@(length)}];
}
return@{@"rangeArray":rangeArray,@"text":text};
}

这个方法在调用时也就是这样了,非常朴实的代码。

NSDictionary*result=[selfscanBegin2Str:@"<"endStr:@">"inText:mutableText];
NSArray*rangeArray=result[@"rangeArray"];
NSMutableString*text=[result[@"text"]mutableCopy];

如果觉得字典不舒服也完全可以用模型,自定义一个对象然后给这个对象的各个属性赋值然后再把这个自定义对象返回回去,虽然代码看上去更科学一点但是需要写一些额外的代码并且不能实现任意可配置(每一种属性都必须要提前设定好),这个和上面算是一个相同的思路就不单独再列一条说了。

2.使用指针的指针

这种方法是我实际使用的方法,就是把需要修改的text的指针的指针传进去,然后在方法的内部对这个实参取一下值得到text的指针。然后通过这个指针修改外部的变量的值。代码实现如下

-(NSArray*)scanBeginStr:(NSString*)beginstrendStr:(NSString*)endstrinText:(NSMutableString**)textPointer{
NSRangerange1,range2;
NSUIntegerlocation=0,length=0;
range1.location=0;
NSMutableString*text=*textPointer;
NSMutableArray*rangeArray=[NSMutableArrayarray];
while(range1.location!=NSNotFound){
range1=[textrangeOfString:beginstr];
range2=[textrangeOfString:endstr];
if(range1.location!=NSNotFound){
location=range1.location;
length=range2.location-range1.location-1;
if(length>5000)break;
[textreplaceOccurrencesOfString:beginstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range1.location+range1.length)];
[textreplaceOccurrencesOfString:endstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range2.location+range2.length-1)];
}
[rangeArrayaddObject:@{@"location":@(location),@"length":@(length)}];
}
returnrangeArray;
}

这个方法在调用时就这么写了,因为mutabletext的修改是无声无息的。

NSArray*rangeArray=[selfscanBegin3Str:@"<"endStr:@">"inText:&mutableText];
//董铂然博客园

  

3.使用block回调

这种方法实际上严格意义来说不能算返回值,但是能够实现返回值的效果。

-(void)scanBeginStr:(NSString*)beginstrendStr:(NSString*)endstrinText:(NSMutableString*)textresult:(void(^)(NSArray*rangeArray,NSMutableString*text))result{
NSRangerange1,range2;
NSUIntegerlocation=0,length=0;
range1.location=0;
NSMutableArray*rangeArray=[NSMutableArrayarray];
while(range1.location!=NSNotFound){
range1=[textrangeOfString:beginstr];
range2=[textrangeOfString:endstr];
if(range1.location!=NSNotFound){
location=range1.location;
length=range2.location-range1.location-1;
if(length>5000)break;
[textreplaceOccurrencesOfString:beginstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range1.location+range1.length)];
[textreplaceOccurrencesOfString:endstrwithString:@""options:NSCaseInsensitiveSearchrange:NSMakeRange(0,range2.location+range2.length-1)];
}
[rangeArrayaddObject:@{@"location":@(location),@"length":@(length)}];
}
result(rangeArray,text);
}

这个block在使用时可能比较特殊就这么写了

[selfscanBeginStr:@"<"endStr:@">"inText:mutabletextresult:^(NSArray*rangeArray,NSMutableString*text){
NSLog(@"%@,%@",rangeArray,text);
}];

如果把block的返回值写成一个字典或是模型也可以,但是那就多此一举了。 返回值不能尝试结构体类型,结构体内不能用OC对象只能用基本数据类型。

其实感觉还有别的方法,比如设置N个成员变量在方法内部计算后重新set也完全可以,但是可能大家也知道成员变量多了比较恶心。最近比较火的函数式编程一直在倡导“方法内不能产生副作用”“实现引用透明” ,如果这么看那后两种方法就不符合FP的规则了,但是用着也有自己的特色。

上一篇  下一篇

I 相关 / Other

前端程序员经常忽视的一个JavaScript面试题

前言年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面

程序员最苦逼!中国单身男女比例太悲催

对于单身汪来说,今天是难过的一天,因为秀恩爱的太多…现在,网易通过汇总大数据,送出了一些情人节有趣的

30行代码实现JavaScript中的MVC

从09年左右开始,MVC逐渐在前端领域大放异彩,并终于在刚刚过去的2015年随着React Native的推出而迎来大爆发

LIGO的科学家们是如何使用Python语言的?

几天前,我们介绍了一个可以分析引力波数据的Python包——GWPY,这个包整理自发现引力波的科研机构LIGO。但

Java中的中文编码问题深入分析

编码问题一直困扰着开发人员,尤其在 Java 中更加明显,因为 Java 是跨平台语言,不同平台之间编码之间的切

I 热点 / Hot