iPhone编程指南学习笔记

UIWindow

在创建应用程序窗口时,您应该总是将其初始的边框尺寸设置为整个屏幕的大小。如果您的窗口是从nib文件装载得到,Interface Builder并不允许创建比屏幕尺寸小的窗口;然而,如果您的窗口是通过编程方式创建的,则必须在创建时传入期望的边框矩形。除了屏幕矩形之外,没有理由传入其它边框矩形。屏幕矩形可以通过UIScreen对象来取得,具体代码如下所示:

UIWindow* aWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

边框、边界、和中心的关系

视图对象通过framebounds、和center属性声明来跟踪自己的大小和位置。frame属性包含一个矩形,即边框矩形,用于指定视图相对于其父视图坐标系统的位置和大小。bounds属性也包含一个矩形,即边界矩形,负责定义视图相对于本地坐标系统的位置和大小。虽然边界矩形的原点通常被设置为 (0, 0),但这并不是必须的。center属性包含边框矩形的中心点。 边框矩形frame是一个通过boundscenter属性计算得到的便利值

但是设置其中的一个属性会引起其它属性的改变,具体关系如下:

  • 当您设置frame属性时,bounds属性的大小会被设置为与frame属性的大小相匹配的值,center属性也会被调整为与新的边框中心点相匹配的值。

  • 当您设置center属性时,frame的原点也会随之改变。

  • 当您设置bounds矩形的大小时,frame矩形的大小也会随之改变。

自动尺寸调整行为

当您改变视图的边框矩形时,其内嵌子视图的位置和尺寸往往也需要改变,以适应原始视图的新尺寸。如果视图的autoresizesSubviews属性声明被设置为YES,则其子视图会根据autoresizingMask属性的值自动进行尺寸调整。
表2-1  自动尺寸调整掩码常量

自动尺寸调整掩码

描述

UIViewAutoresizingNone

这个常量如果被设置,视图将不进行自动尺寸调整。

UIViewAutoresizingFlexibleHeight

这个常量如果被设置,视图的高度将和父视图的高度一起成比例变化。否则,视图的高度将保持不变。

UIViewAutoresizingFlexibleWidth

这个常量如果被设置,视图的宽度将和父视图的宽度一起成比例变化。否则,视图的宽度将保持不变。

UIViewAutoresizingFlexibleLeftMargin

这个常量如果被设置,视图的左边界将随着父视图宽度的变化而按比例进行调整。否则,视图和其父视图的左边界的相对位置将保持不变。

UIViewAutoresizingFlexibleRightMargin

这个常量如果被设置,视图的右边界将随着父视图宽度的变化而按比例进行调整。否则,视图和其父视图的右边界的相对位置将保持不变。

UIViewAutoresizingFlexibleBottomMargin

这个常量如果被设置,视图的底边界将随着父视图高度的变化而按比例进行调整。否则,视图和其父视图的底边界的相对位置将保持不变。

UIViewAutoresizingFlexibleTopMargin

这个常量如果被设置,视图的上边界将随着父视图高度的变化而按比例进行调整。否则,视图和其父视图的上边界的相对位置将保持不变。

添加和移除子视图

在iPhone程序中,有两个地方最常用于创建视图和子视图,它们是应用程序委托对象的applicationDidFinishLaunching:方法和视图控制器loadView方法。

您可以通过下面的方法来操作视图层次中的视图对象:

  • 调用父视图的addSubview:方法来添加视图,该方法将一个视图添加到子视图列表的最后。

  • 调用父视图的insertSubview:...方法可以在父视图的子视图列表中间插入视图。

  • 调用父视图的bringSubviewToFront:sendSubviewToBack:、或exchangeSubviewAtIndex:withSubviewAtIndex:方法可以对父视图的子视图进行重新排序。使用这些方法比从父视图中移除子视图并再次插入要快一些。

  • 调用子视图(而不是父视图)的removeFromSuperview方法可以将子视图从父视图中移除。


描画您的视图内容


如果您能确定自己的描画代码总是以不透明的内容覆盖整个视图的表面,则可以将视图的 opaque 属性声明设置为 YES,以提高描画代码的总体效率。当您将视图标识为不透明时,UIKit会避免对该视图正下方的内容进行描画。这不仅减少了描画开销的时间,而且减少内容合成需要的工作。然而,只有当您能确定视图提供的内容为不透明时,才能将这个属性设置为 YES;如果您不能保证视图内容总是不透明,则应该将它设置为 NO

提高描画性能(特别是在滚动过程)的另一个方法是将视图的clearsContextBeforeDrawing属性设置为NO。当这个属性被设置为YES时,UIKIt会在调用drawRect:方法之前,把即将被该方法更新的区域填充为透明的黑色。将这个属性设置为NO可以取消相应的填充操作,而由应用程序负责完全重画传给drawRect:方法的更新矩形中的部分。这样的优化在滚动过程中通常是一个好的折衷。


调整事件的传递

UIKit为提供了一些简化事件处理、甚至完全关闭事件流的编程接口。下面对这些方法进行总结:

  • 关闭事件的传递。缺省情况下,视图会接收触摸事件。但是,您可以将其userInteractionEnabled属性声明设置为NO,关闭事件传递的功能。隐藏或透明的视图也不能接收事件。

  • 在一定的时间内关闭事件的传递。应用程序可以调用UIApplicationbeginIgnoringInteractionEvents方法,并在随后调用endIgnoringInteractionEvents方法来实现这个目的。前一个方法使应用程序完全停止接收触摸事件消息,第二个方法则重启消息的接收。某些时候,当您的代码正在执行动画时,可能希望关闭事件的传递。

  • 打开多点触摸的传递。 缺省情况下,视图只接收多点触摸序列的第一个触摸事件,而忽略所有其它事件。如果您希望视图处理多点触摸,就必须使它启用这个功能。在代码或Interface Builder的查看器窗口中将视图的multipleTouchEnabled属性设置为YES,就可以实现这个目标。

  • 将事件传递限制在某个单独的视图上。 缺省情况下,视图的exclusiveTouch属性被设置为NO。将这个属性设置为YES会使相应的视图具有这样的特性:即当该视图正在跟踪触摸动作时,窗口中的其它视图无法同时进行跟踪,它们不能接收到那些触摸事件。然而,一个标识为“独占触摸”的视图不能接收与同一窗口中其它视图相关联的触摸事件。如果一个手指接触到一个独占触摸的视图,则仅当该视图是窗口中唯一一个跟踪手指的视图时,触摸事件才会被传递。如果一个手指接触到一个非独占触摸的视图,则仅当窗口中没有其它独占触摸视图跟踪手指时,该触摸事件才会被传递。

  • 将事件传递限制在子视图上。一个定制的UIView类可以通过重载hitTest:withEvent:方法来将多点触摸事件的传递限制在它的子视图上。这个技巧的讨论请参见“事件处理技巧”部分。

事件处理技巧
  • 跟踪UITouch对象的变化

    在事件处理代码中,您可以将触摸状态的相关位置保存下来,以便在必要时和变化之后的UITouch实例进行比较。作为例子,假定您希望将每个触摸对象的最后位置和其初始位置进行比较,则在touchesBegan:withEvent:方法中,您可以通过locationInView:方法得到每个触摸对象的初始位置,并以UITouch对象的地址作为键,将它们存储在CFDictionaryRef封装类型中;然后,在touchesEnded:withEvent:方法中,可以通过传入UITouch对象的地址取得该对象的初始位置,并将它和当前位置进行比较(您应该使用CFDictionaryRef类型,而不是NSDictionary对象,因为后者需要对其存储的项目进行拷贝,而UITouch类并不采纳NSCopying协议,该协议在对象拷贝过程中是必须的)。

  • 对子视图或层上的触摸动作进行触碰测试

    定制视图可以用UIViewhitTest:withEvent:方法或CALayerhitTest:方法来寻找接收触摸事件的子视图或层,进而正确地处理事件。下面的例子用于检测定制视图的层中的“Info” 图像是否被触碰。

    - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
    
        CGPoint location = [[touches anyObject] locationInView:self];
    
        CALayer *hitLayer = [[self layer] hitTest:[self convertPoint:location fromView:nil]];
    
     
        if (hitLayer == infoImage) {
    
            [self displayInfo];
    
        }
    
    }
    

    如果您有一个携带子视图的定制视图,就需要明确自己是希望在子视图的级别上处理触摸事件,还是在父视图的级别上进行处理。如果子视图没有实现touchesBegan:withEvent:touchesEnded:withEvent:、或者touchesMoved:withEvent:方法,则这些消息就会沿着响应者链被传播到父视图。然而,由于多次触碰和多点触摸事件与发生这些动作所在的子视图是互相关联的,所以父视图不会接收到这些事件。为了保证能接收到所有的触摸事件,父视图必须重载hitTest:withEvent:方法,并在其中返回其本身,而不是它的子视图。

  • 确定多点触摸序列中最后一个手指何时离开

    当您希望知道一个多点触摸序列中的最后一个手指何时从视图离开时,可以将传入的集合参数中包含的UITouch对象数量和UIEvent参数对象中与该视图关联的触摸对象数量相比较。请看下面的例子:

    - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
    
        if ([touches count] == [[event touchesForView:self] count]) {
    
            // last finger has lifted....
    
        }
    
    }
    

运动事件

摆动事件和触摸事件有一个很大的不同,当用户开始摆动设备时,系统就会通过motionBegan:withEvent:消息的方式向第一响应者发送一个运动事件,如果第一响应者不能处理,该事件就在响应者链中传递;如果摆动持续的时间小于1秒左右,系统就会向第一响应者发送motionEnded:withEvent:消息;但是,如果摆动时间持续更长,如果系统确定当前的动作不是摆动,则第一响应者会收到一个motionCancelled:withEvent:消息。

拷贝和剪切选定的内容


当用户触碰编辑菜单上的拷贝或剪切命令时,系统会分别调用响应者对象的copy:cut:方法。通常情况下,第一响应者—也就是您的定制视图—会实现这些方法,但如果没有实现的话,该消息会按正常的方式进入响应者链。请注意,UIResponderStandardEditActions非正式协议声明了这些方法。

copy:cut:消息的响应代码中,您需要把和选定内容相对应的对象或数据以尽可能多的表示形式写入到粘贴板上。这个操作涉及到如下这些步骤(假定只有一个的粘贴板数据项):

  1. 标识或取得和选定内容相对应的对象或二进制数据。

    二进制数据必须封装在NSData对象中。其它可以写入到粘贴板的对象必须是属性列表对象—也就是说,必须是下面这些类的对象:NSStringNSArrayNSDictionaryNSDateNSNumber、或者NSURL(有关属性列表对象的更多信息,请参见属性列表编程指南)。

  2. 可能的话,请为对象或数据生成一或多个其它的表示。

    举例来说,在之前提到的为选定图像创建UIImage对象的步骤中,您可以通过UIImageJPEGRepresentationUIImagePNGRepresentation函数将图像转换为不同的表示。

  3. 取得粘贴板对象。

    在很多情况下,使用通用粘贴板就可以了。您可以通过generalPasteboard类方法来取得该对象。

  4. 为写入到粘贴板数据项的每个数据表示分配一个合适的UTI。

    这个主题的讨论请参见“粘贴板的概念”部分。

  5. 将每种表示类型的数据写入到第一个粘贴板数据项中:

    • 向粘贴板对象发送setData:forPasteboardType:消息可以写入数据对象。

    • 向粘贴板对象发送setValue:forPasteboardType:消息可以写入属性列表对象。

  6. 对于剪切(cut:方法)命令,需要从应用程序的数据模型中移除选定内容所代表的对象,并更新视图。

UIKit的图形系统

在iPhone OS上,所有的描画—无论是否采用OpenGL、Quartz、UIKit、或者Core Animation—都发生在UIView对象的区域内。视图定义描画发生的屏幕区域。

重要提示:由于在位图或PDF上下文中进行描画时使用的是左下原点,所以在将描画结果渲染到视图上的时候,必须对坐标系统进行补偿。换句话说,如果您创建一个图像,并调用CGContextDrawImage函数来进行描画,则该图像在缺省情况下是上下颠倒的。为了纠正这个问题,您必须将CTM的y轴进行翻转(即将该值乘以-1),使其原点从左下角移动到视图的左上角。

如果使用UIImage对象来包装您所创建的CGImageRef类型,则不需要修改CTM。UIImage对象会自动对CGImageRef 类型的坐标系统进行翻转补偿。

表4-2  提高描画性能的贴士

Tip

Action

使描画工作最小化

在每个更新周期中,您应该只更新视图中真正发生变化的部分。如果您使用UIView的drawRect:方法来进行描画,则要通过传给该方法的更新矩形来限制描画的范围。对于基于OpenGL的描画,您必须自行跟踪更新区域。

尽可能将视图标识为不透明

合成不透明的视图所需要的开销比合成部分透明的视图要少得多。一个不透明的视图必须不包含任何透明的内容,且视图的opaque属性必须设置为YES

删除不透明的PNG文件中的alpha通道

如果一个PNG图像的每个像素都是不透明的,则将其alpha通道删除可以避免对包含该图像的图层进行融合操作,从而很大程度上简化了该图像的合成,提高描画的性能。

在滚动过程中重用表格单元和视图

应该避免在滚动过程种创建新的视图。创建新视图的开销会减少用于更新屏幕的时间,因而导致滚动不平滑。

避免在滚动过程中清除原先的内容

缺省情况下,在调用drawRect:方法对视图的某个区域进行更新之前,UIKit会清除该区域对应的上下文缓冲区。如果您对视图的滚动事件进行响应,则在滚动过程中反复清除缓冲区的开销是很大的。为了禁止这种行为,可以将clearsContextBeforeDrawing属性设置为NO

在描画过程中尽可能不改变图形状态

改变图形状态需要窗口服务器的参与。如果您要描画的内容使用类似的图形状态,则尽可能将这些内容一起描画,以减少需要改变的状态。

显示键盘

键盘是在视图变为第一响应者时自动被显示的,因此,您通常不需要为了显示它而做什么工作。但是,您可以通过调用视图对象的becomeFirstResponder方法来为可编辑的文本视图显示键盘。调用这个方法可以使目标视图成为第一响应者,并开始编辑过程,其效果和用户触击该视图是一样的。

取消键盘

您可以调用作为当前第一响应者的文本视图的 resignFirstResponder 方法来取消键盘。当文本视图失去第一响应者的状态时,就会结束其当前的编辑会话,将这个变化通知它的 委托 对象,并取消键盘。

移动键盘下面的内容

管理带有键盘的文本对象的最简单方法是将它们嵌入到一个UIScrollView(或其子类,如UITableView)对象。当键盘被显示出来时,您需要做的只是调整滚动视图的尺寸,并将目标文本对象滚动到合适的位置。为此,在UIKeyboardDidShowNotification通告的处理代码中需要进行如下操作:
  1. 取得键盘的尺寸。

  2. 将滚动视图的高度减去键盘的高度。

  3. 将目标文本框滚动到视图中。

     UIScrollView类的scrollRectToVisible:animated:方法

在Web视图中显示内容

如果您的用户界面包含UIWebView对象,就可以显示本地或网络上的内容。对于本地的内容,您可以动态创建,也可以使用文件,然后调用loadData:MIMEType:textEncodingName:baseURL:loadHTMLString:baseURL:方法;如果要从网络加载,则需要创建一个NSURLRequest对象,然后传递给web视图对象的loadRequest:方法。

在发起一个基于网络的请求后,如果由于某种原因必须 释放 web视图,则必须在释放之前取消待处理的请求。为此,您可以调用web视图的 stopLoading 方法。通常情况下,您可以在web视图的视图控制器的 viewWillDisappear: 方法中执行这些代码。如果需要确定一个请求是否处于等待状态,可以通过web视图的 loading 属性来判断。


常用目录

 部分;有关应用程序家目录本身的信息,则请参见 “应用程序沙箱”部分。

表 6-1  iPhone应用程序的目录

目录

描述

<Application_Home>/AppName.app

这是程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。

在iPhone OS 2.1及更高版本的系统,iTunes不对这个目录的内容进行备份。但是,iTunes会对在App Store上购买的应用程序进行一次初始的同步。

<Application_Home>/Documents/

您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备份的信息。有关如何取得这个目录路径的信息,请参见“获取应用程序目录的路径”部分。

iTunes会备份这个目录的内容。

<Application_Home>/Library/Preferences

这个目录包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类或CFPreferences API来取得和设置应用程序的偏好,详情请参见“添加Settings程序包”部分。

iTunes会备份这个目录的内容。

<Application_Home>/Library/Caches

这个目录用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。您的应用程序通常需要负责添加和删除这些文件,但在对设备进行完全恢复的过程中,iTunes会删除这些文件,因此,您应该能够在必要时重新创建。您可以使用“获取应用程序目录的路径” 部分描述的接口来获取该目录的路径,并对其进行访问。

在iPhone OS 2.2及更高版本,iTunes不对这个目录的内容进行备份。

<Application_Home>/tmp/

这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。当您的应用程序不再需要这些临时文件时,应该将其从这个目录中删除(系统也可能在应用程序不运行的时候清理留在这个目录下的文件)。有关如何获得这个目录路径的信息,请参见“获取应用程序目录的路径”部分。

在iPhone OS 2.1及更高版本,iTunes不对这个目录的内容进行备份。

Keychain数据

keychain是一个安全、经过加密保护的容器,用于保存密码和其它秘密信息。应用程序的keychain数据存储在应用程序沙箱之外。如果应用程序被卸载,则该数据会自动被删除。当用户通过iTunes备份应用程序数据时,keychain数据也会被备份。然而,keychain数据只能被恢复到之前做备份的设备上。应用程序的更新并不影响其keychain数据。

有关iPhone OS keychain的更多信息,请参见 Keychain服务编程指南 文档中的“ Keychain服务的概念 ”部分。

文件数据的读写

iPhone OS提供了如下几种读、写、和管理文件的方法:

  • Foundation框架:

    • 如果您可以将应用程序数据表示为一个属性列表,则可以用NSPropertyListSerialization API来将属性列表转换为一个NSData对象,然后通过NSData类的方法将数据对象写入磁盘。

    • 如果应用程序的模型对象采纳了NSCoding协议,则可以通过NSKeyedArchiver类、特别是它的archivedDataWithRootObject:方法将模型对象图进行归档。

    • Foundation框架中的NSFileHandle类提供了随机访问文件内容的方法。

    • Foundation框架中的NSFileManager类提供了在文件系统中创建和操作文件的方法。

  • Core OS调用:

    • 诸如fopenfread、和fwrite这些调用可以用于对文件进行顺序或随机读写。

    • mmapmunmap调用是将大文件载入内存并访问其内容的有效方法。

iPhone音频硬件编解码

下面这些iPhone OS音频格式可以利用硬件解码进行回放:
  • AAC

  • ALAC (Apple Lossless)

  • MP3

通过硬件,设备每次只能播放一路音频。

音频回放和录制格式

下面是一些iPhone OS支持的音频回放格式:

  • AAC

  • HE-AAC

  • AMR (Adaptive Multi-Rate,是一种语音格式)

  • ALAC (Apple Lossless)

  • iLBC (互联网Low Bitrate Codec,另一种语音格式)

  • IMA4 (IMA/ADPCM)

  • 线性PCM (无压缩)
  • µ-law和a-law

  • MP3 (MPEG-1 音频第3层)

下面是一些iPhone OS支持的音频录制格式:

  • ALAC (Apple Lossless)

  • iLBC (互联网Low Bitrate Codec,用于语音)

  • IMA/ADPCM (IMA4)

  • 线性PCM

  • µ-law和a-law



 音频session接口提供的特性

音频会话特性

描述

范畴

范畴是标识一组应用程序音频行为的键。您可以通过范畴的设置来指示自己希望得到的音频行为,比如希望在屏幕锁定状态时继续播放音频。

中断和路由变化

当您的音频发生中断或中断结束,以及当硬件音频路由发生变化时,音频会话会发出通告,使您可以优雅地响应发生在更大音频环境中的变化—比如由于电话呼入而导致的中断。

硬件特征

您可以通过查询音频会话来了解应用程序所在的设备的特征,比如硬件采样率,硬件通道数量,以及是否有音频输入。

举例来说,在使用缺省的音频会话时,如果出现Auto-Lock超时或屏幕锁定,应用程序的音频就会停止。如果您希望在屏幕被锁定时继续播放音频,则必须将下面的代码包含到应用程序的初始化代码中:

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
 系统提供的audio unit

音频单元

描述

转换器单元

转换器单元,类型为kAudioUnitSubType_AUConverter,用于音频数据的格式转换。

iPod均衡器单元

iPod EQ单元,类型为kAudioUnitSubType_AUiPodEQ,提供一个简单的、基于预设的均衡器,可以在应用程序中使用。

3D混音器单元

3D混音器单元,类型为kAudioUnitSubType_AU3DMixerEmbedded,用于混合多个音频流,指定立体声输出移动,操作采样率,等等。

多通道混音器单元

多通道混音器单元,类型为kAudioUnitSubType_MultiChannelMixer,用于将多个音频流混合成为单一的音频流。

一般输出单元

一般输出单元,类型为kAudioUnitSubType_GenericOutput,支持和线性PCM格式互相转换,可以用于开始或结束一个音频单元图。

I/O单元

I/O单元,类型为kAudioUnitSubType_RemoteIO,用于连接音频输入和输入硬件,支持实时I/O。如何使用音频单元的实例代码请见aurioTouch工程。

语音处理I/O单元

语音处理I/O单元,类型为kAudioUnitSubType_VoiceProcessingIO,具有I/O单元的特征,同时为了支持双向交流,加入了回响抑制功能。

音频贴士

贴士

动作

正确地使用压缩音频

对于AAC、MP3、和ALAC (Apple Lossless) 音频,解码过程是由硬件来完成的,虽然比较有效,但同时只能解码一个音频流。如果您需要同时播放多路声音,请使用IMA4 (压缩) 或者线性PCM (无压缩) 格式来存储那些文件。

将音频转换为您需要的数据格式和文件格式

Mac OS X的afconvert工具可以进行很多数据格式和文件类型的转换。请参见“iPhone OS偏好的音频格式” 部分和afconvert工具的手册页面。

评价音频的内存使用问题

当您使用音频队列服务播放音频时,需要编写一个回调函数,负责将较短的音频数据片断发送到音频队列的缓冲区。在某些情况下,将整个音频文件载入内存是最佳的选择,这样可以使播放时的磁盘访问尽最少;而在另外一些情况下,最好的方法则是每次只载入足够填满缓冲区的数据。请测试和评价哪种策略对您的应用程序最好。

限制音频的采样率和位深度,减少音频文件的尺寸

采样率和每个样本的位深度对无压缩音频的尺寸有直接的影响。如果您需要播放很多这样的声音,则应该考虑降低这些指标,以减少音频数据的内存开销。举例来说,相对于使用采样率为44.1 kHz的音频作为声音效果, 您可以使用采样率为32 kHz(或可能更低)的音频,仍然可以得到很合理的品质。

选择恰当的技术

使用Core Audio的系统声音服务来播放警告和用户界面声音效果。当您希望使用便利的高级接口来定位立体声场中的声音,或者要求很低的回放延迟时,则应该使用OpenAL。如果需要从文件或网络数据流中解析出音频数据,可以使用音频文件服务接口。如果只是简单回放一路或多路声音,则应该使用AVAudioPlayer类。对于具有其它音频功能的应用程序,包括音频流的回放和音频录制,可以使用音频队列服务。

低延迟编码

如果需要尽可能低的回放延迟,可以使用OpenAL,或者直接使用I/O单元。

常用的加速计事件更新频率

事件频率(Hz)

用途

10–20

适合用于确定代表设备当前方向的向量。

30–60

适合用于游戏和使用加速计进行实时输入的应用程序。

70–100

适合用于需要检测设备高频运动的应用程序,比如检测用户快速触击或摆动设备。

取得当前设备的方向

如果您需要知道的是设备的大体方向,而不是精确的方向向量,则应该通过UIDevice类的相关方法来取得。使用UIDevice接口比较简单,不需要自行计算方向向量。

在取得当前方向之前,您必须调用beginGeneratingDeviceOrientationNotifications方法,使UIDevice类开始产生设备方向通告。对该方法的调用会打开加速计硬件(否则为了省电,加速计硬件处于关闭状态)。

在打开方向通告的很短时间后,您就可以从UIDevice对象orientation属性声明得到当前的方向。您也可以通过注册接收UIDeviceOrientationDidChangeNotification通告来得到方向信息,当设备的大体方向发生改变时,系统就会发出该通告。设备的方向由UIDeviceOrientation常量来描述,它可以指示设备处于景观模式还是肖像模式,以及设备的正面是朝上还是朝下。这些常量指示的是设备的物理方向,不一定和应用程序的用户界面相对应。

当您不再需要设备的方向信息时,应该调用UIDeviceendGeneratingDeviceOrientationNotifications方法来关闭方向通告,使系统有机会关闭加速计硬件,如果其它地方也不使用的话。

偏好设置元素的类型

元素类型

描述

文本框

文本框类型显示一个可选的标题和一个可编辑的文本输入框,适用于需要用户输入自定义字符串的偏好设置。

这个类型的键是PSTextFieldSpecifier

标题

标题类型显示一个只读的字符串,适用于显示只读字符串的偏好设置(如果偏好设置包含隐含或非直接的值,这个类型可以将可能的值映射为字符串)。

这个类型的键是PSTitleValueSpecifier

拨动开关

拨动开关类型显示一个ON/OFF拨动按键,适用于配置值为二选一的偏好设置。这个类型通常用于表示包含布尔值的偏好设置,但也可以用于表示包含非布尔值的偏好设置。

这个类型的键是PSToggleSwitchSpecifier

滑块

滑块类型显示一个滑块控件,适用于值为一个范围的偏好设置。这个类型的值是一个实数,值的最小和最大值由您来指定。

这个类型的键是PSSliderSpecifier

值列表

值列表类型使用户可以从一个值的列表中选择其一,适用于支持多个互斥值的偏好设置,这些值的类型可以是任意的。

这个类型的键是PSMultiValueSpecifier

组类型使您可以将几组不同的偏好设置组织到一个页面上。组类型并不表示一个可配置的偏好设置,而只是包含一个标题字符串,显示在一或多个可配置的偏好设置之前。

这个类型的键是PSGroupSpecifier

子页面

子页面类型使用户可以访问新的偏好设置页面,适用于实现多层次的偏好设置。有关如何配置和使用这个类型的更多信息,请参见“多层次的偏好设置” 。这个类型的键是 PSChildPaneSpecifier

Settings程序包

在iPhone OS中,开发者通过一种特殊的Settings程序包来指定应用程序的偏好设置,这种程序包命名为Settings.bundle,驻留在应用程序程序包的顶级目录上。该程序包中包含一或多个Settings页面文件,用于定义应用程序偏好设置的详细信息;还可以包含显示偏好设置需要的其它支持文件,比如图像或本地化文件。表9-2列出了一个典型Settings程序包的内容。

表9-2   Settings.bundle目录下的内容

项目名称

描述

Root.plist

这个Settings页面文件包含根页面的偏好设置,它的内容在“Settings页面文件的格式” 部分有更详细的描述。

其它.plist文件

如果您需要通过多个子面板来构建一组有层次结构的偏好设置,则每个子面板的内容都分别存储在不同的Settings页面文件中。您需要负责命名这些文件,并将它们关联到正确的子面板上。

一或多个.lproj 目录

这些目录用于存储Settings页面文件的本地化字符串资源。每个目录都包含一个字符串文件,文件的标题在Settings页面中指定。这些字符串文件为偏好设置提供可以直接显示给用户的本地化内容。

其它图像

如果您使用滑块控件,则可以将滑块的图像存储在程序包的顶级目录下。












你可能感兴趣的:(apple,编程,OS,application,iPhone,UIView)