IOS inPropertyData是什么错误 意外的 in

iOS 音频—— AudioToolbox-ZAKER新闻
CocoaChina
一、前言二、音频文件Audio File Services三、音频文件转换Extended Audio File Services四、音频流Audio File Stream Services五、音频队列Audio Queue Services一、前言AudioToolbox提供的API主要是C 使用起来相对晦涩,针对本文提供了简单的代码示例减小学习的阻力 AudioToolbox采样和采样率sample 是一个声道的一个采样。采样率定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。frame 是最小单位时间点包含的一个或多个声音采样,最小单位时间点取决于声音采样设备,是一个时间点多个采样的集合。譬如,双声道的音频文件,一个时间点有两个声道,一个Frames就包括两个采样。通道是声音的通道的数目。常有单声道和立体声之分。采样位数即采样值或取样值(就是将采样样本幅度量化)。它是用来衡量声音波动变化的一个参数,也可以说是声卡的分辨率。它的数值越大,分辨率也就越高,所发出声音的能力越强。每个采样数据记录的是振幅, 采样精度取决于采样位数的大小:packet 是一个或多个 frame 的集合,一个 packet 包含多少个 frame,是由声音文件格式决定的。譬如 PCM 文件格式中一个 packet 包含 1 个frame。而 MP3 文件格式中一个 packet 包含 1152 个frames。比特率:也称作位速/码率,是指在一个数据流中每秒钟能通过的信息量比特率=采样频率×采样位数×声道数二、Audio File Services2.1、打开或关闭音频文件
OSStatus AudioFileOpenURL ( CFURLRef inFileRef, AudioFilePermissions inPermissions, AudioFileTypeID inFileTypeHint, AudioFileID _Nullable *outAudioFile );
NSString *path = [NSString stringWithFormat:@"%@",[[NSBundle mainBundle] pathForResource:@"MySong" ofType:@"mp3"]];
AudioFileID audioFileID;
OSStatus status = AudioFileOpenURL((__bridge CFURLRef _Nonnull)([NSURL fileURLWithPath:path]), kAudioFileReadPermission, 0, &audioFileID);
if (status != noErr) {
NSLog(@"文件读取失败 %d",status);
}AudioToolbox 函数的返回一般都是OSStatus 成功返回"noErr",OSStatus常见错误CF_ENUM(OSStatus) {
kAudioFileUnspecifiedError
// 0x7768743F,
kAudioFileUnsupportedFileTypeError
// 0x7479703F,
kAudioFileUnsupportedDataFormatError
// 0x666D743F,
kAudioFileUnsupportedPropertyError
// 0x7074793F,
kAudioFileBadPropertySizeError
// 0x2173697A,
kAudioFilePermissionsError
// 0x70726D3F,
kAudioFileNotOptimizedError
// 0x6F70746D,
// file format specific error codes
kAudioFileInvalidChunkError
// 0x63686B3F,
kAudioFileDoesNotAllow64BitDataSizeError
// 0x6F66663F,
kAudioFileInvalidPacketOffsetError
// 0x70636B3F,
kAudioFileInvalidFileError
// 0x6474613F,
kAudioFileOperationNotSupportedError
= 0x6F703F3F,
// 'op??', integer used because of trigraph
// general file error codes
kAudioFileNotOpenError
kAudioFileEndOfFileError
kAudioFilePositionError
kAudioFileFileNotFoundError
= -43};查询 OSStatus错误解释的网站与打开文件对应的close:@param inAudioFile 文件句柄OSStatus AudioFileClose ( AudioFileID inAudioFile );2.2、 读取音频属性获得属性的总体的大小和属性是否可以修改OSStatus AudioFileGetPropertyInfo ( AudioFileID inAudioFile, AudioFilePropertyID inPropertyID, UInt32 *outDataSize, UInt32 *isWritable );在获得属性的具体内容OSStatus AudioFileGetProperty ( AudioFileID inAudioFile, AudioFilePropertyID inPropertyID, UInt32 *ioDataSize, void *outPropertyData );使用in开头函数代表只用作输入(inAudioFile 和inPropertyID,指定了获取哪个文件和哪个属性),out开头的参数代表只用作输出(outPropertyData 指针指向的具体属性内容),io开头的参数既用作输入也用作输出(ioDataSize,接收你分配给outPropertyData的内存缓冲区的大小,然后返回实际上被写入缓冲区的大小),这种参数命名模式是AudioToolbox一个特点。可以提高对当前参数的理解。对于isWritable为true的对其进行设置属性OSStatus AudioFileSetProperty ( AudioFileID inAudioFile, AudioFilePropertyID inPropertyID, UInt32 inDataSize, const void *inPropertyData );查询接口中也是一样,查询文件"inAudioFile"的"inPropertyID"的属性值,结果存放在长度为"ioDataSize"的buffer"outPropertyData"中。属性值有:AudioFilePropertyID意义结果类型kAudioFilePropertyFileFormat音频文件的格式char *kAudioFilePropertyDataFormat音频数据格式AudioStreamPacketDescriptionkAudioFilePropertyIsOptimized是否可以优化0/1kAudioFilePropertyMagicCookieDataMagic Cookie文件头char *kAudioFilePropertyAudioDataByteCount文件长度Uint64kAudioFilePropertyAudioDataPacketCountPacket的数目Uint64kAudioFilePropertyMaximumPacketSize最大的Packet大小Uint32kAudioFilePropertyDataOffset数据的偏移量Uint64kAudioFilePropertyChannelLayout声道结构AudioFormatListItemkAudioFilePropertyDeferSizeUpdates是否更新文件头信息1/0kAudioFilePropertyMarkerList音频中所有markersCFStringRef表示的Markers列表kAudioFilePropertyRegionList音频中所有RegionCFStringRef表示的Region列表kAudioFilePropertyPacketToFrame将包数转换成帧数AudioFramePacketTranslation中mPacket做输入,mFrame做输出kAudioFilePropertyFrameToPacket 将帧数转换成包数AudioFramePacketTranslation中mFrame做输入,mFrameOffsetInPacket,mPacket做输出kAudioFilePropertyPacketToByte将包数转换成字节数AudioFramePacketTranslation中mPacket做输入,mByte做输出kAudioFilePropertyByteToPacket将字节数转换成包数AudioFramePacketTranslation中mByte做输入,mPacket和mByteOffsetInPacket做输出kAudioFilePropertyChunkIDs文件中的chunk编码格式4字符编码格式数组kAudioFilePropertyInfoDictionary字典表示的InfoCFDictionarykAudioFilePropertyPacketTableInfo设置PacketTableInfoPacketTableInfokAudioFilePropertyFormatList支持的格式列表编码格式listkAudioFilePropertyPacketSizeUpperBound理论上的最大Packet大小Uint64kAudioFilePropertyReserveDuration设置写保护区大小,单位为秒Uint32kAudioFilePropertyEstimatedDuration估算的音频时长 , 单位秒Uint32kAudioFilePropertyBitRate码率Uint32kAudioFilePropertyID3TagID3tagvoid *kAudioFilePropertySourceBitDepth位深度Uint32kAudioFilePropertyAlbumArtwork专辑名CFDataRef一些音频压缩的音频格式,例如 MPEG 4 AAC,利用结构体包含音频的元数据。这些结构体就是Magic Cookie,当你用 Audio Queue Services 播放这种格式的音频文件时,你可以从音频文件中获取Magic Cookie ,然后在播放之前添加到音频队列中 UInt32 cookieSize = sizeof (UInt32);
AudioFileGetPropertyInfo (audioFileID,kAudioFilePropertyMagicCookieData,&cookieSize,NULL);
if (!status && cookieSize) {
char* magicCookie =(char *) malloc (cookieSize);
AudioFileGetProperty (audioFileID,kAudioFilePropertyMagicCookieData,&cookieSize,magicCookie);
AudioQueueSetProperty (inAQ,kAudioQueueProperty_MagicCookie,magicCookie,cookieSize);
free (magicCookie);
}2.3、 读取音频数据AudioFileReadPackets 已经被废弃使用 不建议使用 主要使用的是AudioFileReadPacketDataOSStatus AudioFileReadBytes ( AudioFileID inAudioFile, Boolean inUseCache, SInt64 inStartingByte, UInt32 *ioNumBytes, void *outBuffer );OSStatus AudioFileReadPacketData ( AudioFileID inAudioFile, Boolean inUseCache, UInt32 *ioNumBytes, AudioStreamPacketDescription *outPacketDescriptions, SInt64 inStartingPacket, UInt32 *ioNumPackets, void *outBuffer );OSStatus AudioFileReadPackets ( AudioFileID inAudioFile, Boolean inUseCache, UInt32 *outNumBytes, AudioStreamPacketDescription *outPacketDescriptions, SInt64 inStartingPacket, UInt32 *ioNumPackets, void *outBuffer );// 已经废弃AudioFileID inAudioFile 文件句柄Boolean inUseCache 是否缓存读取的数据UInt32 *outNumBytes : 最终读到数据的大小AudioStreamPacketDescription *outPacketDescriptions : 一个存放AudioStreamPacketDescription的BufferSInt64 inStartingPacket : 起始的PacketUInt32 *ioNumPackets : 当输入时表示要读取的Packet数目,输出时表示最终读入的Packet数目void *outBuffer : 数据读到的具体buffer位置三、Extended Audio File ServicesAudio File Services提供的api 需要传入冗长的参数 Extended Audio File Services可以看做是对Audio File Services的封装,当时更多的实际开发我们用它来做音频文件类型的转换。3.1、打开和关闭音频数据打开文件:OSStatus ExtAudioFileOpenURL ( CFURLRef inURL, ExtAudioFileRef _Nullable *outExtAudioFile );当操作完以后,通过Dispose来回收资源,区分于其他的Close:OSStatus ExtAudioFileDispose ( ExtAudioFileRef inExtAudioFile );3.2、读取音频数据和"Audio ToolBox"的其他属性操作一样,Ext接口提供的属性操作也是分为两步,先获取属性基本信息,如大小:OSStatus ExtAudioFileGetPropertyInfo ( ExtAudioFileRef inExtAudioFile, ExtAudioFilePropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable );然后在获得属性内容:OSStatus ExtAudioFileGetProperty ( ExtAudioFileRef inExtAudioFile, ExtAudioFilePropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData );或者设置属性内容:OSStatus ExtAudioFileSetProperty ( ExtAudioFileRef inExtAudioFile, ExtAudioFilePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData ); _outputFormat.mSampleRate = 44100;
_outputFormat.mBitsPerChannel = 16;
_outputFormat.mChannelsPerFrame = 2;
_outputFormat.mFormatID = kAudioFormatMPEGLayer3;
UInt32 descSize = sizeof(AudioStreamBasicDescription);
ExtAudioFileGetProperty(_audioFileRef, kExtAudioFileProperty_FileDataFormat, &descSize, &_inputFormat);
_inputFormat.mSampleRate = _outputFormat.mSampleR
_inputFormat.mChannelsPerFrame = _outputFormat.mChannelsPerF
_inputFormat.mBytesPerFrame = _inputFormat.mChannelsPerFrame* _inputFormat.mBytesPerF
_inputFormat.mBytesPerPacket =
_inputFormat.mFramesPerPacket*_inputFormat.mBytesPerF
ExtAudioFileSetProperty(_audioFileRef,
kExtAudioFileProperty_ClientDataFormat,
sizeof(AudioStreamBasicDescription),
&_inputFormat),kExtAudioFileProperty_Xxxx : 源文件的相关属性,也就是原来什么格式的数据(MP3/AAC),他的基本属性。kExtAudioFileProperty_ClientXxx: 读出时的数据格式,Ext在读出时会自动帮我们做编解码操作,这个是处理后的结果所以在读取之前,一定要记得设置"kExtAudioFileProperty_ClientDataFormat"属性,设置其输出的数据格式,ExtAudioFilePropertyID意义结果数据类型是否可读写kExtAudioFileProperty_FileDataFormat源音频数据的格式AudioStreamBasicDescription只读kExtAudioFileProperty_FileChannelLayout源音频数据的通道格式AudioChannelLayout读写kExtAudioFileProperty_ClientDataFormat读出来后的音频数据的格式AudioStreamBasicDescription读写kExtAudioFileProperty_ClientChannelLayout读出来后的音频数据的通道格式AudioChannelLayout读写kExtAudioFileProperty_CodecManufacturer是否使用硬件编解码UInt32(kAppleHardwareAudioCodecManufacturer or kAppleSoftwareAudioCodecManufacturer)读写kExtAudioFileProperty_AudioConverter指定的编解码工具AudioConverterRef只读kExtAudioFileProperty_AudioFile对应的AudioFileIDAudioFileID只读kExtAudioFileProperty_FileMaxPacketSize源音频数据最大的Packet大小Uint32只读kExtAudioFileProperty_ClientMaxPacketSize读出后音频数据最大的Packet大小Uint32只读kExtAudioFileProperty_FileLengthFrames帧数SInt64只读kExtAudioFileProperty_ConverterConfig指定编解码器CFArray读写kExtAudioFileProperty_IOBufferSizeBytes编解码使用的缓冲区大小UInt32读写kExtAudioFileProperty_IOBuffer编解码使用的缓冲区void *读写kExtAudioFileProperty_PacketTable设置PacketTableAudioFilePacketTableInfo读写struct AudioBufferList{
AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements#if defined(__cplusplus) && CA_STRICTpublic:
AudioBufferList() {}private:
Copying and assigning a variable length struct is problematic so turn their use into a
compile time error for eacy spotting.
AudioBufferList(const AudioBufferList&);
AudioBufferList&
operator=(const AudioBufferList&);#endif};typedef struct AudioBufferList
AudioBufferLstruct AudioBuffer{
mDataByteS
void* __nullable
mD};typedef struct AudioBuffer
AudioB写入文件内容写入和读取类似,只是要预先填好BufferList的内容:OSStatus ExtAudioFileWrite ( ExtAudioFileRef inExtAudioFile, UInt32 inNumberFrames, const AudioBufferList *ioData );同时写入还有个非阻塞的版本,当调用" ExtAudioFileDispose "会最终保证所有数据都写入到磁盘中。OSStatus ExtAudioFileWriteAsync ( ExtAudioFileRef inExtAudioFile, UInt32 inNumberFrames, const AudioBufferList *ioData );四、Audio File Stream Services对于网络音频文件 大多采用的是边读取边播放,这个时候就用到了Audio File Stream4.1、初始化音频流extern OSStatus
AudioFileStreamOpen (
void * __nullable
inClientData,
AudioFileStream_PropertyListenerProc
inPropertyListenerProc,
AudioFileStream_PacketsProc
inPacketsProc,
AudioFileTypeID
inFileTypeHint,
AudioFileStreamID __nullable * __nonnull outAudioFileStream)inClientData上下文对象;AudioFileStream_PropertyListenerProc 在调用AudioFileStreamParseBytes歌曲信息的回调;AudioFileStream_PacketsProc 在调用AudioFileStreamParseBytes对音频数据的回调,主要用于音频帧的数据分类存储。AudioFileTypeID 文件类型的提示,如果无法确定类型可以传入0AudioFileStreamID,获取当前实例对应的AudioFileStreamID,使用其他AudioFileStream API需要传入。4.2、读取音频流extern OSStatusAudioFileStreamParseBytes(
AudioFileStreamID
inAudioFileStream,
inDataByteSize,
const void *
AudioFileStreamParseFlags
inFlags)AudioFileStreamID,AudioFileStreamOpen获取的的AudioFileStreamID;inDataByteSize,解析的数据字节长度;inData,解析的数据;AudioFileStreamParseFlags说本次的解析和上一次解析是否是连续的关系,如果是连续的传入0,否则传kAudioFileStreamParseFlag_Discontinuity。4.3、解析文件格式信息typedef void (*AudioFileStream_PropertyListenerProc)(
inClientData,
AudioFileStreamID
inAudioFileStream,
AudioFileStreamPropertyID
inPropertyID,
AudioFileStreamPropertyFlags *
ioFlags);根据当前的PropertyID调用AudioFileStreamGetProperty获取当前音频文件的具体信息if (inPropertyID ==
kAudioFileStreamProperty_DataFormat) {
UInt32 outDataSize = sizeof(AudioStreamBasicDescription);
AudioFileStreamGetProperty(inAudioFileStream, inPropertyID,
&outDataSize, &_audioStreamDescription);
}typedef void (*AudioFileStream_PacketsProc)(
inClientData,
inNumberBytes,
inNumberPackets,
const void *
inInputData,
AudioStreamPacketDescription
*inPacketDescriptions);inClientData 上下文对象;inumberOfBytes,读取的数据长度;inumberOfPackets,读取的数据帧数量;inInputData,读取的数据字节;AudioStreamPacketDescription类型的数组,存储了当前帧数据的偏移量和大小。图片来源:Audio Streaming ( Audio Queue )五、Audio Queue Services5.1、初始化Audio QueueAudioQueueNewOutput(
const AudioStreamBasicDescription *inFormat,
AudioQueueOutputCallback
inCallbackProc,
void * __nullable
inUserData,
CFRunLoopRef __nullable
inCallbackRunLoop,
CFStringRef __nullable
inCallbackRunLoopMode,
AudioQueueRef __nullable * __nonnull outAQ)AudioStreamBasicDescription音频数据格式类型,是一个AudioStreamBasicDescription对象,是使用AudioFileStream或者AudioFile解析出来的数据格式信息;AudioQueueOutputCallback是某块Buffer被使用之后的回调;inUserData 上下文对象;inCallbackRunLoop为AudioQueueOutputCallback需要在的哪个RunLoop上被回调,如果传入NULL的话就会再AudioQueue的内部RunLoop中被回调,所以一般传NULL就可以了;inCallbackRunLoopMode为RunLoop模式,如果传入NULL就相当于kCFRunLoopCommonModes,也传NULL就可以了;inFlags是保留字段,目前没作用,传0;返回生成的AudioQueue实例;5.2、创建bufferextern OSStatusAudioQueueAllocateBuffer(
AudioQueueRef
inBufferByteSize,
AudioQueueBufferRef __nullable * __nonnull outBuffer)AudioQueueRef 创建的AudioQueueinBufferByteSize buffer的大小AudioQueueBufferRef 返回当前创建的buffer实例。5.3、将buffer放入音频队列extern OSStatusAudioQueueEnqueueBuffer(
AudioQueueRef
AudioQueueBufferRef
inNumPacketDescs,
const AudioStreamPacketDescription * __nullable inPacketDescs)AudioQueueRef 创建的AudioQueueAudioQueueBufferRef buffer对象AudioStreamPacketDescription数组的数量AudioStreamPacketDescription数组的指针地址作者:baxiang链接:http://www.jianshu.com/p/3a92e0c7bf74著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。原网页已经由ZAKER转码以便在移动设备上查看
相关标签:
原网页已经由 ZAKER 转码排版
太平洋电脑网24分钟前
雷锋网1小时前
TechWeb4小时前
TechWeb5小时前
驱动之家22小时前
瘾科技昨天
钛媒体6分钟前
中关村在线3小时前
钛媒体3小时前
钛媒体3小时前
钛媒体4小时前
凤凰科技13小时前
铅笔道昨天
科技频道15小时前
App精选4小时前51CTO旗下网站
那些 iOS 7 中容易被忽视的新特性总结
新颖以及备受争议的特性,让iOS7成为iOS系统史上最大的发布之一。除非你是那种用整晚的时间阅读iOS7更新内容的那种人,那么就可能会忽视掉一两个新的变化。在本篇文章中我们汇总了一份较完备的iOS7重要且有趣的新变化。
作者:佚名来源:cocoachina| 16:33
iOS7到现在已经发布了有一段时间了。相信你现在已经了解了它那些开创性的视觉设计,已经了解了它的新的API,比如说SpirteKit,UIKit Dynamics以及TextKit,作为开发者,也很可能已经在使用Xcode5进行开发了。
然而,它新颖以及备受争议的特性,让iOS7成为iOS系统史上最大的发布之一。除非你是那种用整晚的时间阅读iOS7更新内容的那种人,那么就可能会忽视掉一两个新的变化。
在本篇文章中我们汇总了一份较完备的iOS7重要且有趣的新变化。现在让我们一起来看看是否有一些新变化你以前没有注意到呢?
坏消息,好消息,以及非常好的消息
iOS7有一些坏消息,一些好消息,还有一些非常好的消息。
坏消息:iOS7中有一些可能会对app造成破坏性的变化,你必须要了解。如果你还不知道这些变化的话,那么你就需要好好看看他们了,因为当他们在iOS7上运行的时候可能会造成app崩溃!
好消息:有一些你熟悉的特性和API在iOS7中得到了优化&&但是还有一些其他的特性被遗弃了。花点时间来看看这些变化,对你app的升级来说是个很好的投资。
非常好的消息:iOS7的发布确实震动了手机开发世界,随着这个重大事件的发生,随之而来的也有一系列新功能,它们可能会给你现有app带来新特色,也可能成为将来开发的app创新的触发剂。
本篇文章搜罗了iOS7容易忽略的一些特点,将它们分为了以上三类。以下的列表,如果有感兴趣的内容可以直接跳过去看,也可以按照文章的顺序来了解所有的变化。
坏消息:可以导致app崩溃的变化
1.已禁用-[UIDevice uniqueIdentifier]
2.UIPasteboard由共享变为沙盒化了
3.MAC地址不能再用来识别设备
4.iOS现在要求app如需使用麦克风,需要征得用户同意
好消息:性能提高以及被遗弃的功能
5.-[NSArray firstObject]的实现
6.增加了instancetype
7.设置UIImage的渲染模式:UIImage.renderingMode
8.tintColor VS barTintColor
9.去掉了纹理颜色
10.UIButtonTypeRoundRect被UIButtonTypeSystem取代了
非常好的消息:新功能
11.检查无线路由是否可用
12.了解蜂窝网络
13.通过iCloud同步用户设备的密码
14.使用NSAttributedString显示HTML
15.使用原生的Base64
16.使用UIApplicationUserDidTakeScreenshotNotification来检查截图
17.实现多语言语音合成
18.使用了新的手势识别
19.使用UIScrollViewKeyboardDismissMode实现了Message app的行为
20.使用Core Image来检测眨眼以及微笑
21.给UITextView增加了链接
坏消息:可以导致app崩溃的变化
这个部分的变化你可能在了解iOS7的时候已经注意到了,但是你也许没有意识到这些变化的程度,以及它们如何可能会影响你的app。事实上这些变化都和用户隐私相关,而你应该知道对苹果来说用户隐私有多么重要!
1.已禁用-[UIDevice uniqueIdentifier]
苹果总是把用户的隐私看的很重要。-[UIDevice
uniqueIdentifier]在iOS5实际在iOS5的时候已经被遗弃了,但是iOS7中已经完全的禁用了它。Xcode5甚至不会允许你编译包 含了指引到-[UIDevice uniqueIdentifier]的app。此外,iOS7之前的使用了-[UIDevice
uniqueIdentifier]
的app如果在iOS7上运行,它不会返回设备的UUID,而是会返回一串字符串,以FFFFFFFF开头,跟着-[UIDevice
identifierForVendor]的十六进制值。
2.UIPasteboard由共享变为沙盒化了
UIPasteboard过去是用来做app之间的数据分享的。UIPasteboard本无问题,但是开发者开始使用它来存储标识符,和其他的相关app分享这些标识符的时候问题就出现了。有一个使用这种把戏的就是OpenUDID。
在iOS7中,使用 +[UIPasteboard pasteboardWithName:create:]和
+[UIPasteboard pasteboardWithUniqueName]创建剪贴板,而且只对相同的app
group可见,这样就让OpenUDID不那么有用了。
3.MAC地址不能再用来设别设备
现在仍可以使用这个MAC
还有一个生成iOS设备唯一标示符的方法是使用iOS设备的Media Access
Control(MAC)地址。一个MAC地址是一个唯一的号码,它是物理网络层级方面分配给网络适配器的。这个地址苹果还有其他的名字,比如说是硬件地 址(Hardware Address)或是Wifi地址,都是指同样的东西。
有很多工程和框架都使用这个方法来生成唯一的设备ID。比如说ODIN。然而,苹果并不希望有人通过MAC地址来分辨用户,所以如果你在iOS7系统上查询MAC地址,它现在只会返回02:00:00:00:00:00。
现在苹果明确的表明你应该使用-[UIDevice
identifierForVendor]或是-[ASIdentifierManager
advertisingIdentifier]来作为你框架和应用的唯一标示符。坦白的来说,应对这些变化也不是那么的难,见以下代码片段:
NSString&*identifierForVendor&=&[[UIDevice&currentDevice].identifierForVendor&UUIDString];&NSString&*identifierForAdvertising&=&[[ASIdentifierManager&sharedManager].advertisingIdentifier&UUIDString];&
每种方法都适配一种特别的用法:
identifierForVendor对供应商来说是唯一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,如果用户删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致。
advertisingIdentifier会返回给在这个设备上所有软件供应商相同的 一个值,所以只能在广告的时候使用。这个值会因为很多情况而有所变化,比如说用户初始化设备的时候便会改变。
如果你想了解更多的信息,你可以看看。
4.iOS现在要求app如需使用麦克风,需要征得用户同意
以前如果app需要使用用户的位置,通讯录,日历,提醒以及照片,接受推送消息,使用用户的社交网络的时候需要征得用户的同意。现在在iOS7 当中,使用麦克风也需要取得用户同意了。如果用户不允许app使用麦克风的话,那么需要使用麦克风的app就不能接收不到任何声音。
以下的代码是用来查询用户是否允许app使用麦克风:
&&&[[AVAudioSession&sharedInstance]&requestRecordPermission:^(BOOL&granted)&{&&&&&if&(granted)&{&&&&&&&&&&&&&&}&else&{&&&&&&&&&&&&&&}&}];&
你同时还要注意,如果你在获得用户的同意之前使用任何方法来使用麦克风的话,会引起iOS系统弹出以下警示栏:
好消息:性能提高以及被遗弃的功能
以上就是一些重要的更新,他们可能会让你现在的app崩溃。然后,还有一些变化可能会对你的app造成影响,但是你不会在第一时间发现这些变化。
5.-[NSArray firstObject]的实现
-[NSArray firstObject]可能是Objective-C中被调用做多的API。在Open
Radar上一个简单的调查显示有一些需求苹果已经做了记录。好消息是现在这些需求已经得到了解决。.
firstObject的使用可以追溯到iOS4.0,但是那时仅仅是一个私有方法。在iOS7以前,工程师用下面的方式来使用它:
NSArray&*arr&=&@[];&id&item&=&[arr&firstObject];&&id&item&=&[arr&count]&&&0&?&arr[0]&:&&
因为上面的方式很平常,有些人将它作为一个类增加到NSArray中,然后创建他们自己的firstObject方法。在Github上做一个快速搜索你可以看到过去这种方式是有多么的常用。
这个方法的问题是这个方法的名字必须是唯一的,否则的话这个方法所引发的问题无法预估。请确保检查你是否有任何自定义的代码在NSArray上实现了firstObject,如果有的话看看它是否是必须的,不是必须的话就把它全部移除。
6.增加了instancetype
instancetype让iOS7API变得更加难懂。苹果改变了大部分 initializer和简易构造函数(convenience constructors),用instancetype代替id作返回类型。但是这个instancetype是什么呢?
instancetype用来在声明一个方法时告诉编译器其返回类型,它表示返回调用该方法的类的对象。这比之前返回id的通常做法要好,编译 器可以对返回类型做一些检查,如果出现错误,在编译时就能提醒你,而不是在程序运行时发生崩溃。同时,在调用子类方法时,使用它还可以省去对返回值的强制 类型转换,编译器能够正确推断方法的返回值类型。
要说到instancetaype的缺点和优点吗?基本上,在任何可能的情况下都可以使用它。
如果需要更多关于instancetype的信息,你可以看看。
7.设置UIImage的渲染模式:UIImage.renderingMode
着色(Tint Color)是iOS7界面中的一个重大改变,你可以设置一个UIImage在渲染时是否使用当前视图的Tint
Color。UIImage新增了一个只读属性:renderingMode,对应的还有一个新增方 法:imageWithRenderingMode:,它使用UIImageRenderingMode枚举值来设置图片的renderingMode属 性。该枚举中包含下列值:
UIImageRenderingModeAutomatic&&UIImageRenderingModeAlwaysOriginal&&UIImageRenderingModeAlwaysTemplate&&
renderingMode属性的默认值是UIImageRenderingModeAutomatic,即UIImage是否使用Tint Color取决于它显示的位置。其他情况可以看下面的图例
以下的代码说明了使用一个既定的rendering模式创建图片是多么简单:
UIImage&*img&=&[UIImage&imageNamed:@&myimage&];&img&=&[img&imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];&
8.tintcolor VS barTintColor
iOS7中你可以使用一个给定的颜色,甚至是记入颜色主题来给整个app着色,帮助你的app脱颖而出。设置app的tint color很简答,只要使用UIView的新属性tintColor即可。
这个属性是否听上去很熟悉呢?应该很熟悉,有些类,比如说UINaviagtionBar,UISearchBar,UITabBar以及UIToolbar已经有了这么命名的属性。他们现在有了一个新的属性:barTintColor。
为了避免使用新属性的时候犯错误,如果你的appp需要支持iOS6以前的系统的时候,请检查一下。
UINavigationBar&*bar&=&self.navigationController.navigationB&UIColor&*color&=&[UIColor&greenColor];&if&([bar&respondsToSelector:@selector(setBarTintColor:)])&{&&&&&&bar.barTintColor&=&&}&else&{&&&&&&bar.tintColor&=&&}&
9.去掉了纹理颜色
纹理颜色?对,不再使用他们了。不能再创建可以展现纹理的颜色。根据UIInterface.h文件中的注释,-[UIColor
groupTableViewBackgroundColor]应该是要在iOS6当中即被删除了,但是它仅仅只是不像之前那样返回纹理颜色了。然而,以 下的颜色在iOS7当中被删除了:
+&(UIColor&*)viewFlipsideBackgroundC&+&(UIColor&*)scrollViewTexturedBackgroundC&+&(UIColor&*)underPageBackgroundC&
10.UIButtonTypeRoundRect被UIButtonTypeSystem取代了
在iOS开发刚开始就陪伴着你的老朋友现在也被删除了,它就是UIButtonTypeRoundRect ,被新的UIButtonTypeSystem取代了。
非常好的消息:新功能
如果每次iOS系统的发布都没有一些新的功能会是什么样子?这些新功能相信大部分开发者已经知道了,你可能会发现一些新颖的方式将它们整合到你的app中去!
11.检查无线路由是否可用
定制一个视频播放器的能力在iOS版本每次的发布中一直有所进步。比如说,在iOS6之前,你不能在MPVolumeView中改变AirPlay的icon。
在iOS7当中,你可以通过AirPlay,蓝牙或是其他的虚线机制了解是否有一个远程的设备可用。了解它的话,就可以让你的app在恰当的时候做恰当的事,比如说,在没有远程设备的时候就不显示AirPlay的icon。
以下是新增加到MPVolumeView的新属性和推送
@property&(nonatomic,&readonly)&BOOL&wirelessRoutesA&&@property&(nonatomic,&readonly)&BOOL&wirelessRouteA&&NSString&*const&MPVolumeViewWirelessRoutesAvailableDidChangeN&NSString&*const&MPVolumeViewWirelessRouteActiveDidChangeN&
12.了解蜂窝网络
在iOS7之前,是使用Reachability来检测设备是否连接到WWAN或是Wifi的。iOS7在这个基础上更进了一步,它会告诉你的 设备连接上的是那种蜂窝网络,比如说是Edge网络,HSDPA网络,或是LTE网络。告诉用户他们连接上的是哪种网络可以优化用户体验,因为这样他们会 知道网速如何,不会去请求需要高网速的网络请求。
这是CTTelephonyNetworkInfo的部分功能,它是CoreTelephony框架的一部分。iOS7还增加了 currentRadioAccessTechnology属性和 CTRadioAccessTechnologyDidChangeNotification到这个类。还有一些新的字符串常量来定义可能的值,比如说是 CTRadioAccessTechnologyLTE。
以下代码告诉你在app delegate中如何使用这个新功能:
@import&CoreTelephony.CTTelephonyNetworkI&&&@interface&AppDelegate&()&&@property&(nonatomic,&strong)&CTTelephonyNetworkInfo&*networkI&&&@end&&&@implementation&ViewController&&&-&(BOOL)application:(UIApplication&*)application&didFinishLaunchingWithOptions:(NSDictionary&*)launchOptions&{&&&&&&&&self.networkInfo&=&[[CTTelephonyNetworkInfo&alloc]&init];&&&NSLog(@&Initial&cell&connection:&%@&,&self.networkInfo.currentRadioAccessTechnology);&&&[[NSNotificationCenter&defaultCenter]&addObserver:self&selector:@selector(radioAccessChanged)&name:&CTRadioAccessTechnologyDidChangeNotification&object:nil];&&&&&&}&&&-&(void)radioAccessChanged&{&&&NSLog(@&Now&you&re&connected&via&%@&,&self.networkInfo.currentRadioAccessTechnology);&}&&&@end&
注意:研究一下CTTelephonyNetworkInfo.h 文件来看看是否有其他无线网络类型的的字符串常量。如果设备没有连上的话,currentRadioAccessTechnology 则会返回nil。
13.通过iCloud同步用户设备的密码
iOS7以及Mavericks增加了iCloud Keychain来提供密码,以及iCloud中一些敏感数据的同步。开发者可以通过keychain中的kSecAttrSynchronizable key来遍历dictionary对象。
由于直接处理keychain比较难,封装库提供了一个简单的处理keychain的方法。SSKeychain封装库可能是最有名的的一个,作为一种福利,现在它支持在iCloud同步。
以下代码片段显示了如何使用SSKeychain:
#import&&SSKeychain.h&&&&-&(BOOL)saveCredentials:(NSError&**)error&{&&&&&SSKeychainQuery&*query&=&[[SSKeychainQuery&alloc]&init];&&&&&query.password&=&@&MySecretPassword&;&&&&&query.service&=&@&MyAwesomeService&;&&&&&query.account&=&@&John&Doe&;&&&&&query.synchronizable&=&YES;&&&&&return&[query&save:&error];&}&&&-&(NSString&*)savedPassword:(NSError&**)error&{&&&&&SSKeychainQuery&*query&=&[[SSKeychainQuery&alloc]&init];&&&&&query.service&=&@&MyAwesomeService&;&&&&&query.account&=&@&John&Doe&;&&&&&query.synchronizable&=&YES;&&&&&query.password&=&&&&&&if&([query&fetch:&error])&{&&&&&&&&&return&query.&&&&&}&&&&&return&&}&
不要忘记CocoaPods是快速便捷安装SSKeychian的好方法。
14.使用NSAttributedString显示HTML
在app中使用Webviews有时会让人非常沮丧,即使只是显示少量的HTMLneirong ,Webviews也会消耗大量的内容。现在iOS7让这些变得简单了,你可以从用少量代码在HTML文件中创建一个NSAttributedString,比如:
&&&&NSString&*html&=&@&&bold&Wow!&/bold&&Now&&em&iOS&/em&&can&create&&h3&NSAttributedString&/h3&&from&HTMLs!&;&&&&&NSDictionary&*options&=&@{NSDocumentTypeDocumentAttribute:&NSHTMLTextDocumentType};&&&&&&&&&&&NSAttributedString&*attrString&=&[[NSAttributedString&alloc]&initWithData:[html&dataUsingEncoding:NSUTF8StringEncoding]&&&&&options:options&documentAttributes:nil&error:nil];&&&&&&&&现在你可以在任意的UIKit对象上使用NSAttributedString&了,比如说是一个UILabel或是一个UITextField,见以下代码:&&&&&&#import&&SSKeychain.h&&&&&&&&&&&&-&(BOOL)saveCredentials:(NSError&**)error&{&&&&&&&&&SSKeychainQuery&*query&=&[[SSKeychainQuery&alloc]&init];&&&&&&&&&query.password&=&@&MySecretPassword&;&&&&&&&&&query.service&=&@&MyAwesomeService&;&&&&&&&&&query.account&=&@&John&Doe&;&&&&&&&&&query.synchronizable&=&YES;&&&&&&&&&return&[query&save:&error];&&&&&}&&&&&&&&&&&-&(NSString&*)savedPassword:(NSError&**)error&{&&&&&&&&&SSKeychainQuery&*query&=&[[SSKeychainQuery&alloc]&init];&&&&&&&&&query.service&=&@&MyAwesomeService&;&&&&&&&&&query.account&=&@&John&Doe&;&&&&&&&&&query.synchronizable&=&YES;&&&&&&&&&query.password&=&&&&&&&&&&if&([query&fetch:&error])&{&&&&&&&&&&&&&return&query.&&&&&&&&&}&&&&&&&&&return&&
注意:NSHTMLTextDocumentType
只是NSDocumentTypeDocumentAttribute
key一种可能的值。你还可以使用NSPlainTextDocumentType,NSRTFTextDocumentType或是 NSRTFDTextDocumentType。
你还可以从NSAttributedString中创建一个HTML字符串,如下:
NSAttributedString&*attrS&&NSDictionary&*options&=&@{NSDocumentTypeDocumentAttribute:&NSHTMLTextDocumentType};&&&NSData&*htmlData&=&[attrString&dataFromRange:NSMakeRange(0,&[attrString&length])&documentAttributes:options&error:nil];&NSString&*htmlString&=&[[NSString&alloc]&initWithData:htmlData&encoding:NSUTF8StringEncoding];&
现在你估计在app中会更多的使用HTML了。
15.使用原生的Base64
Base64是使用ASCII码显示二进制数据的一种流行方法。直到现在,开发者还不得不使用开源的工具来编码解码Base64的内容。
现在iOS7引入了以下四种新的NSData方法来操作Base64编码的数据:
&&&&&&-&(id)initWithBase64EncodedString:(NSString&*)base64String&options:(NSDataBase64DecodingOptions)&&&&&-&(NSString&*)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)&&&&&-&(id)initWithBase64EncodedData:(NSData&*)base64Data&options:(NSDataBase64DecodingOptions)&&&&&-&(NSData&*)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)&
这些方法可以帮助你轻易的将NSData对象转化为Base64,或者将Base64转化为NSData object。见以下的例子:
NSData*&sampleData&=&[@&Some&sample&data&&dataUsingEncoding:NSUTF8StringEncoding];&&&NSString&*&base64String&=&[sampleData&base64EncodedStringWithOptions:0];&NSLog(@&Base64-encoded&string&is&%@&,&base64String);&&&&NSData*&dataFromString&=&[[NSData&alloc]&initWithBase64EncodedString:base64String&options:0];&NSLog(@&String&is&%@&,[NSString&stringWithUTF8String:[dataFromString&bytes]]);&&
如果你需要支持iOS6或者更早以前的系统,你可以使用以下两个方法:
&&&&-&(id)initWithBase64Encoding:(NSString&*)base64S&-&(NSString&*)base64E&
16.使用UIApplicationUserDidTakeScreenshotNotification来检查截图
在iOS7之前,像Snapshot或是Facebook
Poke这样的app是使用一些很精巧的方法来检测用户是否有截图。然而,iOS7提供一个崭新的推送方 法:UIApplicationUserDidTakeScreenshotNotification。只要像往常一样订阅即可知道什么时候截图了。
注意:UIApplicationUserDidTakeScreenshotNotification
将会在截图完成之后显示。现在在截图截取之前无法得到通知。希望苹果会在iOS8当中增加 UIApplicationUserWillTakeScreenshotNotification。
17.实现多语言语音合成
如果可以让app说话会不会很好呢?iOS7加入了两个新类:AVSpeechSynthesizer 以及AVSpeechUtterance。这两个类可以给你的app发声。很有意思不是吗?有多种语言可供选择&&Siri不会说的语言也有,比如说巴西葡萄牙语。
使用这两个类给app提供语言合成的功能非常简单。AVSpeechUtterance 代表你想说什么,如何说。AVSpeechSynthesizer 用来发出这些声音,见以下代码片段:
AVSpeechSynthesizer&*synthesizer&=&[[AVSpeechSynthesizer&alloc]&init];&AVSpeechUtterance&*utterance&=&&&[AVSpeechUtterance&speechUtteranceWithString:@&Wow,&I&have&such&a&nice&voice!&];&utterance.rate&=&AVSpeechUtteranceMaximumSpeechRate&/&4.0f;&utterance.voice&=&[AVSpeechSynthesisVoice&voiceWithLanguage:@&en-US&];&&[synthesizer&speakUtterance:utterance];&
18.使用了新的UIScreenEdgePanGestureRecognizer&
UIScreenEdgePanGestureRecognizer 继承自UIPanGestureRecognizer ,它可以让你从屏幕边界即可检测手势。
使用新的手势识别器很简单,见以下:
UIScreenEdgePanGestureRecognizer&*recognizer&=&[[UIScreenEdgePanGestureRecognizer&alloc]&initWithTarget:self&action:&@selector(handleScreenEdgeRecognizer:)];&recognizer.edges&=&UIRectEdgeL&&[self.view&addGestureRecognizer:recognizer];&
19.使用UIScrollViewKeyboardDismissMode实现了Message app的行为
像Messages app一样在滚动的时候可以让键盘消失是一种非常好的体验。然而,将这种行为整合到你的app很难。幸运的是,苹果给UIScrollView添加了一个很好用的属性keyboardDismissMode,这样可以方便很多。
现在仅仅只需要在Storyboard中改变一个简单的属性,或者增加一行代码,你的app可以和办到和Messages app一样的事情了。
这个属性使用了新的UIScrollViewKeyboardDismissMode enum枚举类型。这个enum枚举类型可能的值如下:
UIScrollViewKeyboardDismissModeNone&&&&&&&&&UIScrollViewKeyboardDismissModeOnDrag&&&&&&&UIScrollViewKeyboardDismissModeInteractive&&&pulled&upward&again&to&cancel&the&dismiss&
以下是让键盘可以在滚动的时候消失需要设置的属性:
20.使用Core Image来检测眨眼以及微笑
iOS给Core Image增加了两种人脸检测功能:CIDetectorEyeBlink以及CIDetectorSmile。这也就是说你现在可以在照片中检测微笑以及眨眼。
以下是在app中使用它的方法:
UIImage&*image&=&[UIImage&imageNamed:@&myImage&];&CIDetector&*detector&=&[CIDetector&detectorOfType:CIDetectorTypeFace&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&context:nil&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&options:@{CIDetectorAccuracy:&CIDetectorAccuracyHigh}];&&&NSDictionary&*options&=&@{&CIDetectorSmile:&@YES,&CIDetectorEyeBlink:&@YES&};&&&NSArray&*features&=&[detector&featuresInImage:image.CIImage&options:options];&&&for&(CIFaceFeature&*feature&in&features)&{&&&&&NSLog(@&Bounds:&%@&,&NSStringFromCGRect(feature.bounds));&&&&&&&if&(feature.hasSmile)&{&&&&&NSLog(@&Nice&smile!&);&&&&&}&else&{&&&&&NSLog(@&Why&so&serious?&);&&&&&}&&&&&if&(feature.leftEyeClosed&||&feature.rightEyeClosed)&{&&&&&NSLog(@&Open&your&eyes!&);&&&&&}&}&
21.给UITextView增加了链接
现在在iOS添加你自己的Twitter账户更加简单了,现在你可以给一个NSAttributedString增加链接了,然后当它被点击的时候唤起一个定制的action。
首先,创建一个NSAttributedString然后增加给它增加一个NSLinkAttributeName 属性,见以下:
NSMutableAttributedString&*attributedString&=&[[NSMutableAttributedString&alloc]&initWithString:@&This&is&an&example&by&@marcelofabri_&];&[attributedString&addAttribute:NSLinkAttributeName&&&&&&&&&&&&&&&&&&&&&&&&&&value:@&username://marcelofabri_&&&&&&&&&&&&&&&&&&&&&&&&&&&range:[[attributedString&string]&rangeOfString:@&@marcelofabri_&]];&&&&&NSDictionary&*linkAttributes&=&@{NSForegroundColorAttributeName:&[UIColor&greenColor],&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NSUnderlineColorAttributeName:&[UIColor&lightGrayColor],&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NSUnderlineStyleAttributeName:&@(NSUnderlinePatternSolid)};&&&&textView.linkTextAttributes&=&linkA&&textView.attributedText&=&attributedS&textView.delegate&=&&
这样就可以让链接在文本中显示。然而,你也可以控制当链接被点击的时候会发生什么,实现这个可以使用UITextViewDelegate协议的新的shouldInteractWithURL方法,就像这样:
-&(BOOL)textView:(UITextView&*)textView&shouldInteractWithURL:(NSURL&*)URL&inRange:(NSRange)characterRange&{&&&&&if&([[URL&scheme]&isEqualToString:@&username&])&{&&&&&&&&&NSString&*username&=&[URL&host];&&&&&&&&&&&&&&&&&&&&&&&&&&&return&NO;&&&&&}&&&&&return&YES;&&}&
现在这些新功能就介绍完了。
【移动开发视频课程推荐】
【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
热点热点头条热点聚焦
24H热文一周话题本月最赞
讲师:30642人学习过
讲师:131985人学习过
讲师:251680人学习过
精选博文论坛热帖下载排行
《网管员必读―服务器与数据存储》全面、系统地介绍了在中、高级网络管理和网络工程实施中两个重要方面的主流技术和应用:硬件服务器和数据...
订阅51CTO邮刊

我要回帖

更多关于 deepin双系统时间错误 的文章

 

随机推荐