iOS 7
随着保密协议的解除,我们终于可以开始聊一聊iOS 7里面精彩的新的API了。新的操作系统增加了_非常多_的API,根据Apple在WWDC上的统计,有1500之多。(同意,虽然其中很大一部分可能只是将id
变成了instancetype
,但是不管怎么说,这是个大数目)。
在接下来的几周里,我们将会深入了解iOS 7的很多新增加的功能,但不管我们对这次版本的发布有多兴奋,本周的主题是谈一谈那些隐藏在平淡光彩下的宝石:NSData
Base64 编码, NSURLComponents
, NSProgress
, NSProcess
activities, CIDetector
, CIDetector
, SSReading
, AVCapture
, AVSpeech
, 以及 MKDistance
.
NSData (NSDataBase64Encoding)
Base64是作为ASCII文本为二进制编码的常用方式之一。因为很多核心技术都被设计用来支持文本,而不是原始二进制,所以Base64在网络上被广泛的使用。比如,CSS可以通过inline data://
URIs嵌入图像,这通常是Base64编码的。另一个例子是基本认证
头标,这也是通过Base64来编码用户名/密码对,这也比它们完全暴露要稍好一些。
很长时间以来,这个重要却无聊的功能完全没有被实现,使得成千上万的开发者不得不从论坛中粘贴复制随机的代码片段。这个疏忽就和iOS5之前的JSON一样突出且恼人。
但这再也不是问题了!iOS7终于加入Base64了:
NSString *string = @"Lorem ipsum dolor sit amet.";
NSString *base64Encoded String = [[string data Using Encoding:NSUTF8String Encoding] base64Encoded String With Options:0];
NSLog(@"%@", base64Encoded String); // @"TG9y ZW0ga XBzd W0g ZG9s YXIgc2l0IGFt ZXQu"
NSURLComponents & NSCharacterSet (NSURLUtilities)
Foundation得天独厚地拥有许多能应用在URI上的功能。不幸的是,许多用来操控URL的API都因为NSURL
的不可变性而仍在使用NSString
.
NSURLComponents
戏剧性地改变了这个情况。你可以把它想成NSMutable
:
NSURLComponents *components = [NSURLComponents components With String:@"https://nshipster.com"];
components.path = @"/i OS7";
components.query = @"foo=bar";
NSLog(@"%@", components.scheme); // @"http"
NSLog(@"%@", [components URL]); // @"https://nshipster.com/i OS7?foo=bar"
每一个URL components的property还有一个percent
的演变(比如user
& percent
),通过这个变形就不需要使用其他额外的URI特殊字符百分号编码。
你也许会问,哪些字符是特殊的呢?这取决于你所指的是URL的哪一部分。好消息是NSCharacter
增加了一个用来在iOS 7里允许使用新的URL字符的新的类别:
+ (id)URLUser
Allowed Character Set + (id)URLPassword
Allowed Character Set + (id)URLHost
Allowed Character Set + (id)URLPath
Allowed Character Set + (id)URLQuery
Allowed Character Set + (id)URLFragment
Allowed Character Set
NSProgress
NSProgress
是一个很难描述的类。它的作用既像观察员又像代表/协调员,可以处理报告以及监测的进程。它可以与OS X上的系统级别进程进行集成,但也可以被插入到面向用户的用户界面。它可以指定处理器来暂停和取消,然后前进到实际进行这项工作的操作上去。
任何具有完成的和整体的概念的单位都属于NSProgress
的候选人,不管它是写入文件的字节,大型渲染工作的帧的数目,或者从服务器上下载的文件。
NSProgress
可以被用来通过本地化方式简单的报告整体的进程:
NSProgress *progress = [NSProgress progress With Total Unit Count:100];
progress.completed Unit Count = 42;
NSLog(@"%@", [progress localized Description]); // 42% completed
…或者我们可以给它一个完全停止工作的处理器:
NSTimer *timer = [NSTimer timer With Time Interval:1.0
target:self
selector:@selector(increment Completed Unit Count:) user Info:nil
repeats:YES];
progress.cancellation Handler = ^{
[timer invalidate];
};
[progress cancel];
NSProgress
在OS X Mavericks的使用环境下,会更有意义,但就目前而言,它仍然仅仅是一个用于封装工作单位共享模式的有用的类。
NSArray -firstObject
欢呼吧!NSRange
中方便使用的-last
终于被延伸到NSArray
的第一个成员了。(虽然_自从_iOS 4以来就有私有API可以实现这个功能,不过这个不再重要了。)
看哪!
NSArray *array = @[@1, @2, @3];
NSLog(@"First Object: %@", [array first Object]); // 1
NSLog(@"Last Object: %@", [array last Object]); // 3
真让人神清气爽啊!
CIDetectorSmile & CIDetectorEyeBlink
随口说两句,最有能力照到我们尴尬照片的设备,同时也是最有能力把这些照片和数百万人分享的设备这件事情难道不应该引起人们的关注吗?这仅仅是一个想法。
自从iOS5以来,Core Image框架提供了通过CIDetector
类可实现的面部监测与识别功能。如果在照片中识别面部还不够疯狂,那么在iOS 7中我们甚至可以识别这张脸是在微笑还是闭眼睛了。*不寒而栗*
这又是一个免费应用的想法,这里的代码片段或许可以被照相机使用来仅仅存储带有笑脸的照片:
@import Core Image;
CIDetector *smile Detector = [CIDetector detector Of Type:CIDetector Type Face
context:context
options:@{CIDetector Tracking: @YES,
CIDetector Accuracy: CIDetector Accuracy Low}];
NSArray *features = [smile Detector features In Image:image options:@{CIDetector Smile:@YES}];
if (([features count] > 0) && (((CIFace Feature *)features[0]).has Smile)) {
UIImage Write To Saved Photos Album(image, self, @selector(did Finish Writing Image), features);
} else {
self.label.text = @"Say Cheese!"
}
AVCaptureMetaDataOutput
通过AVCapture
扫瞄各式各样的UPC,QR码和条形码,是iOS 7的新功能。你所需要做的就是将它设置为AVCapture
的输出,并相应地实现capture
方法:
@import AVFoundation;
AVCapture Session *session = [[AVCapture Session alloc] init];
AVCapture Device *device = [AVCapture Device default Device With Media Type:AVMedia Type Video];
NSError *error = nil;
AVCapture Device Input *input = [AVCapture Device Input device Input With Device:device
error:&error];
if (input) {
[session add Input:input];
} else {
NSLog(@"Error: %@", error);
}
AVCapture Metadata Output *output = [[AVCapture Metadata Output alloc] init];
[output set Metadata Object Types:@[AVMetadata Object Type QRCode]];
[output set Metadata Objects Delegate:self queue:dispatch_get_main_queue()];
[session add Output:output];
[session start Running];
#pragma mark - AVCapture Metadata Output Objects Delegate
- (void)capture Output:(AVCapture Output *)capture Output
did Output Metadata Objects:(NSArray *)metadata Objects
from Connection:(AVCapture Connection *)connection
{
NSString *QRCode = nil;
for (AVMetadata Object *metadata in metadata Objects) {
if ([metadata.type is Equal To String:AVMetadata Object Type QRCode]) {
// This will never happen; nobody has ever scanned a QR code... ever
QRCode = [(AVMetadata Machine Readable Code Object *)metadata string Value];
break;
}
}
NSLog(@"QR Code: %@", QRCode);
}
AVFoundation
支持你所听到过的任何码(可能还有一些你没听到过的):
AVMetadata
Object Type UPCECode AVMetadata
Object Type Code39Code AVMetadata
Object Type Code39Mod43Code AVMetadata
Object Type EAN13Code AVMetadata
Object Type EAN8Code AVMetadata
Object Type Code93Code AVMetadata
Object Type Code128Code AVMetadata
Object Type PDF417Code AVMetadata
Object Type QRCode AVMetadata
Object Type Aztec Code
如果不出意外,AVCapture
还可以使简单地为iPhone和iPad生成一个Passbook的Pass阅读器成为可能。Passbook仍有很多没有被实现的潜力,所以我们希望这个API能够被广泛的应用。
SSReadingList
虽然阅读以前存储下来内容的人数仅仅比使用过QR码的人数多一点,但iOS 7增加了Safari服务框架功能以添加Safari阅读列表仍然是个好事情。
@import Safari Services;
NSURL *URL = [NSURL URLWith String:@"https://nshipster.com/ios7"];
[[SSReading List default Reading List] add Reading List Item With URL:URL
title:@"NSHipster"
preview Text:@"..."
error:nil];
AVSpeechSynthesizer
文本到语音自从60年代面市以来,对于易接近性和恶作剧爱好者来说一直是电脑的杀手级功能。
iOS 7将Siri的说&拼写的便捷的能力加入到了一个新的类AVSpeech
:
AVSpeech Synthesizer *synthesizer = [[AVSpeech Synthesizer alloc] init];
AVSpeech Utterance *utterance = [AVSpeech Utterance speech Utterance With String:@"Just what do you think you're doing, Dave?"];
utterance.rate = AVSpeech Utterance Minimum Speech Rate; // Tell it to me slowly
[synthesizer speak Utterance:utterance];
MKDistanceFormatter
最后,我们由另外一个新的并且值得注意的类来结束这次展示。这个类的出现使得NSHipster们高兴地大呼“终于来了!”: MKDistance
。
就像被宣传时说的那样,MKDistance
提供了一种将距离通过英制或者公制单位转换成为本地字符串的方法:
@import Core Location;
@import Map Kit;
CLLocation *san Francisco = [[CLLocation alloc] init With Latitude:37.775 longitude:-122.4183333];
CLLocation *portland = [[CLLocation alloc] init With Latitude:45.5236111 longitude:-122.675];
CLLocation Distance distance = [portland distance From Location:san Francisco];
MKDistance Formatter *formatter = [[MKDistance Formatter alloc] init];
formatter.units = MKDistance Formatter Units Imperial;
NSLog(@"%@", [formatter string From Distance:distance]); // 535 miles
这就是本周的全部啦!这仅仅是iOS 7的伟大的新功能中的一小部分。还想知道的更多?看看Apple开发者中心的“What’s New in iOS 7”手册吧。