怎么能够停滞不前查出 iOS8 中哪些函数被替换了,哪些函数不能再用了,谢谢!

iOS崩溃调试的使用和技巧总结
招聘信息:
本文是投稿文章,作者:在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢!获取崩溃信息在iOS中获取崩溃信息的方式有很多,比较常见的是使用友盟、百度等第三方分析工具,或者自己收集崩溃信息并上传公司服务器。下面列举一些我们常用的崩溃分析方式:使用友盟、百度等第三方崩溃统计工具。自己实现应用内崩溃收集,并上传服务器。Xcode-Devices中直接查看某个设备的崩溃信息。使用苹果提供的Crash崩溃收集服务。收集崩溃信息苹果给我们提供了异常处理的类,NSException类。这个类可以创建一个异常对象,也可以通过这个类获取一个异常对象。这个类中我们最常用的还是一个获取崩溃信息的C函数,我们可以通过这个函数在程序发生异常的时候收集这个异常。//&将系统提供的获取崩溃信息函数写在这个方法中,以保证在程序开始运行就具有获取崩溃信息的功能
&&-&(BOOL)application:(UIApplication&*)application&didFinishLaunchingWithOptions:(NSDictionary&*)launchOptions&{
&&&&&//&将下面C函数的函数地址当做参数
&&&&&NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
&&&&&return&YES;
&&//&设置一个C函数,用来接收崩溃信息
&&void&UncaughtExceptionHandler(NSException&*exception){
&&&&&&//&可以通过exception对象获取一些崩溃信息,我们就是通过这些崩溃信息来进行解析的,例如下面的symbols数组就是我们的崩溃堆栈。
&&&&&&NSArray&*symbols&=&[exception&callStackSymbols];
&&&&&&NSString&*reason&=&[exception&reason];
&&&&&&NSString&*name&=&[exception&name];
&&}我们也可以通过下面方法获取崩溃统计的函数指针:&&NSUncaughtExceptionHandler&*handler&=&NSGetUncaughtExceptionHandler();dSYM 符号集进行崩溃分析,首先要弄懂一个概念,就是符号集。符号集是我们对ipa文件进行打包之后,和.app文件同级的后缀名为.dSYM的文件,这个文件必须使用Xcode进行打包才有。每一个.dSYM文件都有一个UUID,和.app文件中的UUID对应,代表着是一个应用。而.dSYM文件中每一条崩溃信息也有一个单独的UUID,用来和程序的UUID进行校对。我们如果不使用.dSYM文件获取到的崩溃信息都是不准确的。符号集中存储着文件名、方法名、行号的信息,是和可执行文件的16进制函数地址对应的,通过分析崩溃的.Crash文件可以准确知道具体的崩溃信息。我们每次Archive一个包之后,都会随之生成一个dSYM文件。每次发布一个版本,我们都需要备份这个文件,以方便以后的调试。进行崩溃信息符号化的时候,必须使用当前应用打包的电脑所生成的dSYM文件,其他电脑生成的文件可能会导致分析不准确的问题。Archive当程序崩溃的时候,我们可以获得到崩溃的错误堆栈,但是这个错误堆栈都是0x开头的16进制地址,需要我们使用Xcode自带的symbolicatecrash工具来将.Crash和.dSYM文件进行符号化,就可以得到详细崩溃的信息。崩溃分析命令行解析Crash文件通过Mac自带的命令行工具解析Crash文件需要具备三个文件symbolicatecrash,Xcode自带的崩溃分析工具,使用这个工具可以更精确的定位崩溃所在的位置,将0x开头的地址替换为响应的代码和具体行数。我们打包时产生的dSYM文件。崩溃时产生的Crash文件。我在解析崩溃信息的时候,首先在桌面上建立一个Crash文件夹,然后将.Crash、.dSYM、symbolicatecrash放在这个文件夹中,这样进入这个文件夹下,直接一行命令就解决了。symbolicatecrash我们可以在下面路径下可以找到,我用的是Xcode7,其他版本Xcode路径不一样,请自行Google。/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash然后Window->Organizer->Archives中,选中archive的版本右击,选择Show in Finder就可以获取dSYM文件了。dSYM文件将.Crash、.dSYM、symbolicatecrash三个文件都放在我们在桌面建立的Crash文件夹中。Crash文件夹开启命令行工具,进入崩溃文件夹中cd /Users/username/Desktop/崩溃文件夹使用命令解析Crash文件./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash如果上面命令不成功,使用命令检查一下环境变量xcode-select -print-path返回结果:/Applications/Xcode.app/Contents/Developer/如果不是上面的结果,需要使用下面命令设置一下导出的环境变量,然后重复上面解析的操作。export DEVELOPER_DIR=/Applications/XCode.app/Contents/Developer解析完成后会生成一个新的.Crash文件,这个文件中就是崩溃详细信息。图中红色标注的部分就是我们代码崩溃的部分。解析完成的结果注意,以下情况不会有崩溃信息产生:内存访问错误(不是野指针错误)低内存,当程序内存使用过多会造成系统低内存的问题,系统会将程序内存回收因为某种原因触发看门狗机制通过Xcode查看设备崩溃信息除了上面的系统分析工具来进行分析,如果是我们自己直接使用手机连接崩溃或者崩溃之后连接手机,选择window-> devices -> 选择自己的手机 -> view device logs 就可以查看我们的崩溃信息了。view device logs只要手机上的应用是这台电脑安装打包的,这样的崩溃信息系统已经为我们符号化好了,我们只需要进去之后等一会就行(不要相信这里面的进度刷新,并不准确),如果还是没有符号化完毕 ,我们选择文件,然后右击选择Re-Sysbomlicate就可以。如果是使用其他电脑进行的打包,我们可以在这里面将Crash文件导出,自己通过命令行的方式进行解析。使用第三方崩溃分析工具现在有很多第三方工具都可以进行崩溃统计分析,使用比较多的是友盟崩溃统计,友盟崩溃统计被集成在友盟SDK中,具体用法直接看官方文档是最好的方法,下面列出友盟崩溃统计文档地址。在这里我并不推荐友盟这个第三方,而是推荐一个更好用的第三方—。这个第三方和友盟的最大区别就是可以直接将崩溃信息分析结合dSYM分析好,在web网页上展现出来,而且还可以统计崩溃数、崩溃设备、系统版本等。下面是我公司使用bugHD统计的一些崩溃情况bugHD在bugHD服务器已经帮我们使用dSYM将崩溃符号化完成。我们可以通过点击某条崩溃,查看详细崩溃堆栈,以及崩溃设备分布和系统分布。详细分布苹果自带崩溃统计工具苹果在Xcode中为我们集成了崩溃统计功能,在Window->Organizer->Crashes中可以看到Crashes苹果自带的崩溃统计工具并不推荐用,如果想要使用这个功能,需要用户在iPhone中进行设置设置->隐私->诊断与用量->诊断与用量数据(iOS8一下在通用中设置)选择自动发送,并与开发者共享即可第三方工具恶意覆盖崩溃收集统计函数应该只进行一次调用,如果用第三方的话也最好只用一个第三方,这样我们获取崩溃统计信息的途径也是唯一的。第三方统计工具并不是用的越多越好,使用多个崩溃收集第三方会导致NSSetUncaughtExceptionHandler()函数指针的恶意覆盖,导致有些第三方不能收到崩溃信息。现在很多第三方崩溃收集工具为了确保自己能最大可能的收集到崩溃信息,会对NSSetUncaughtExceptionHandler()函数指针的恶意覆盖。因为这个函数是将函数地址当做参数传递,所以只要重复调用就会被覆盖,这样就不能保证崩溃收集的稳定性。我们解析崩溃信息时,看到崩溃堆栈只有main.m文件中的崩溃,并且可以确定不是因为main.m文件中的bug导致的崩溃,就基本可以确定是NSSetUncaughtExceptionHandler()函数指针被恶意覆盖。被恶意覆盖的崩溃堆栈
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量11469点击量10373点击量10370点击量9927点击量9730点击量8646点击量7972点击量6688点击量6509
&2015 Chukong Technologies,Inc.
京公网安备89今天看啥 热点:
在iOS 8中使用UIAlertController,ios8使用技巧iOS 8的新特性之一就是让接口更有适应性、更灵活,因此许多视图控制器的实现方式发生了巨大的变化。全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸变化效果(比如说旋转)中发挥了重要的作用,它有效地节省了程序员们的工作量(天地良心啊)。还有,某些旧的UIKit控件也同样发生了许多变化,比如说Alert Views、Action Sheets、Popovers以及Search Bar Controllers。本文将会对Alert Views和Action Sheets发生的改变进行一个大致的介绍,我们会采用Objective-C和swift两种语言同时进行代码说明。
UIAlertView
随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化。下面的代码片段展示了如何初始化和显示一个带有&取消&和&好的&按钮的对话框视图。
Objective-C版本:
UIAlertView&*alertview&=&[[UIAlertView&alloc]&initWithTitle:@"标题"&message:@"这个是UIAlertView的默认样式"&delegate:self&cancelButtonTitle:@"取消"&otherButtonTitles:@"好的",&nil];
[alertview&show];
UIAlertView的默认样式
swift版本和Objective-C版本不同,在swift中,alertView的初始化只允许创建拥有一个取消按钮的对话框视图。或许您可以看到带有otherButtonTitles的init方法,但是很遗憾,这个方法是没有办法通过编译的。
var&alertView&=&UIAlertView(title:&"标题",&message:&"这个是UIAlertView的默认样式",&delegate:&self,&cancelButtonTitle:&"取消")
alertView.show()
swift版本的UIAlertView
要能够创建和上面Objective-C版本相同的对话框视图,我们可以采取曲线救国的方法,虽然麻烦了些,但是我们为了目的可以不择手段的,是吧?
var&alertView&=&UIAlertView()
alertView.delegate&=&self
alertView.title&=&"标题"
alertView.message&=&"这个是UIAlertView的默认样式"
alertView.addButtonWithTitle("取消")
alertView.addButtonWithTitle("好的")
alertView.show()
您也可以通过更改UIAlertView的alertViewStyle属性来实现输入文字、密码甚至登录框的效果。
UIAlertView文本对话框
UIAlertView密码对话框
UIAlertView登录对话框
UIAlertViewDelegate协议拥有响应对话框视图的按钮动作的回调方法。还有当文本框内容改变时,调用alertViewShouldEnableOtherButton:方法可以让按钮动态地可用或者不可用。
要说明一点,苹果官方现在并不提倡在iOS 8中使用UIAlertView,取而代之的是UIAlertController。下面我们就来介绍UIAlertController的使用方法。
UIAlertController
在iOS 8中,UIAlertController在功能上是和UIAlertView以及UIActionSheet相同的,UIAlertController以一种模块化替换的方式来代替这两货的功能和作用。是使用对话框(alert)还是使用上拉菜单(action sheet),就取决于在创建控制器时,您是如何设置首选样式的。
一个简单的对话框例子
您可以比较一下两种不同的创建对话框的代码,创建基础UIAlertController的代码和创建UIAlertView的代码非常相似:
Objective-C版本:
UIAlertController&*alertController&=&[UIAlertController&alertControllerWithTitle:@"标题"&message:@"这个是UIAlertController的默认样式"&preferredStyle:UIAlertControllerStyleAlert];
swift版本:
var&alertController&=&UIAlertController(title:&"标题",&message:&"这个是UIAlertController的默认样式",&preferredStyle:&UIAlertControllerStyle.Alert)
同创建UIAlertView相比,我们无需指定代理,也无需在初始化过程中指定按钮。不过要特别注意第三个参数,要确定您选择的是对话框样式还是上拉菜单样式。
通过创建UIAlertAction的实例,您可以将动作按钮添加到控制器上。UIAlertAction由标题字符串、样式以及当用户选中该动作时运行的代码块组成。通过UIAlertActionStyle,您可以选择如下三种动作样式:常规(default)、取消(cancel)以及警示(destruective)。为了实现原来我们在创建UIAlertView时创建的按钮效果,我们只需创建这两个动作按钮并将它们添加到控制器上即可。
Objective-C版本:
UIAlertAction&*cancelAction&=&[UIAlertAction&actionWithTitle:@"取消"&style:UIAlertActionStyleCancel&handler:nil];
UIAlertAction&*okAction&=&[UIAlertAction&actionWithTitle:@"好的"&style:UIAlertActionStyleDefault&handler:nil];
[alertController&addAction:cancelAction];
[alertController&addAction:okAction];
swift版本:
var&cancelAction&=&UIAlertAction(title:&"取消",&style:&UIAlertActionStyle.Cancel,&handler:&nil)
var&okAction&=&UIAlertAction(title:&"好的",&style:&UIAlertActionStyle.Default,&handler:&nil)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
最后,我们只需显示这个对话框视图控制器即可:
Objective-C版本:
[self&presentViewController:alertController&animated:YES&completion:nil];
swift版本:
self.presentViewController(alertController,&animated:&true,&completion:&nil)
UIAlertController默认样式
按钮显示的次序取决于它们添加到对话框控制器上的次序。一般来说,根据苹果官方制定的《iOS 用户界面指南》,在拥有两个按钮的对话框中,您应当将取消按钮放在左边。要注意,取消按钮是唯一的,如果您添加了第二个取消按钮,那么你就会得到如下的一个运行时异常:
* Terminating app due to uncaught exception &NSInternalInconsistencyException&, reason: &UIAlertController can only have one action with a style of UIAlertActionStyleCancel&
异常信息简洁明了,我们在此就不赘述了。
&警示&样式
什么是&警示&样式呢?我们先不着急回答这个问题,先来看一下下面关于&警示&样式的简单示例。在这个示例中,我们将前面的示例中的&好的&按钮替换为了&重置&按钮。
Objective-C版本:
UIAlertAction&*resetAction&=&[UIAlertAction&actionWithTitle:@"重置"&style:UIAlertActionStyleDestructive&handler:nil];
[alertController&addAction:resetAction];
swift版本:
var&resetAction&=&UIAlertAction(title:&"重置",&style:&UIAlertActionStyle.Destructive,&handler:&nil)
alertController.addAction(resetAction)
&警示&样式
可以看出,我们新增的那个&重置&按钮变成了红色。根据苹果官方的定义,&警示&样式的按钮是用在可能会改变或删除数据的操作上。因此用了红色的醒目标识来警示用户。
文本对话框
UIAlertController极大的灵活性意味着您不必拘泥于内置样式。以前我们只能在默认视图、文本框视图、密码框视图、登录和密码输入框视图中选择,现在我们可以向对话框中添加任意数目的UITextField对象,并且可以使用所有的UITextField特性。当您向对话框控制器中添加文本框时,您需要指定一个用来配置文本框的代码块。
举个栗子吧,要重新建立原来的登录和密码样式对话框,我们可以向其中添加两个文本框,然后用合适的占位符来配置它们,最后将密码输入框设置使用安全文本输入。
Objective-C版本:
UIAlertController&*alertController&=&[UIAlertController&alertControllerWithTitle:@"文本对话框"&message:@"登录和密码对话框示例"&preferredStyle:UIAlertControllerStyleAlert];
[alertController&addTextFieldWithConfigurationHandler:^(UITextField&*textField){
&&&&textField.placeholder&=&@"登录";
[alertController&addTextFieldWithConfigurationHandler:^(UITextField&*textField)&{
&&&&textField.placeholder&=&@"密码";
&&&&textField.secureTextEntry&=&YES;
swift版本:
alertController.addTextFieldWithConfigurationHandler&{&
(textField:&UITextField!)&-&&Void&in
&&&&textField.placeholder&=&"登录"
alertController.addTextFieldWithConfigurationHandler&{&
(textField:&UITextField!)&-&&Void&in
&&&&textField.placeholder&=&"密码"
&&&&textField.secureTextEntry&=&true
在&好的&按钮按下时,我们让程序读取文本框中的值。
Objective-C版本:
UIAlertAction&*okAction&=&[UIAlertAction&actionWithTitle:@"好的"&style:UIAlertActionStyleDefault&handler:^(UIAlertAction&*action)&{
&&&&UITextField&*login&=&alertController.textFields.firstO
&&&&UITextField&*password&=&alertController.textFields.lastO
swift版本:
var&okAction&=&UIAlertAction(title:&"好的",&style:&UIAlertActionStyle.Default)&{
(action:&UIAlertAction!)&-&&Void&in
&&&&var&login&=&alertController.textFields?.first&as&UITextField
&&&&var&password&=&alertController.textFields?.last&as&UITextField
如果我们想要实现UIAlertView中的委托方法alertViewShouldEnableOtherButton:方法的话可能会有一些复杂。假定我们要让&登录&文本框中至少有3个字符才能激活&好的&按钮。很遗憾的是,在UIAlertController中并没有相应的委托方法,因此我们需要向&登录&文本框中添加一个Observer。Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。我们可以在构造代码块中添加如下的代码片段来实现。
Objective-C版本:
[alertController&addTextFieldWithConfigurationHandler:^(UITextField&*textField){
&&&&[[NSNotificationCenter&defaultCenter]&addObserver:self&selector:@selector(alertTextFieldDidChange:)&name:UITextFieldTextDidChangeNotification&object:textField];
swift版本:
alertController.addTextFieldWithConfigurationHandler&{
(textField:&UITextField!)&-&&Void&in
&&&&NSNotificationCenter.defaultCenter().addObserver(self,&selector:&Selector("alertTextFieldDidChange:"),&name:&UITextFieldTextDidChangeNotification,&object:&textField)
当视图控制器释放的时候我们需要移除这个Observer,我们通过在每个按钮动作的handler代码块(还有其他任何可能释放视图控制器的地方)中添加合适的代码来实现它。比如说在okAction这个按钮动作中:
Objective-C版本:
UIAlertAction&*okAction&=&[UIAlertAction&actionWithTitle:@"好的"&style:UIAlertActionStyleDefault&handler:^(UIAlertAction&*action)&{
&&&&[[NSNotificationCenter&defaultCenter]&removeObserver:self&name:UITextFieldTextDidChangeNotification&object:nil];
swift版本:
var&okAction&=&UIAlertAction(title:&"好的",&style:&UIAlertActionStyle.Default)&{
(action:&UIAlertAction!)&-&&Void&in
&&&&NSNotificationCenter.defaultCenter().removeObserver(self,&name:&UITextFieldTextDidChangeNotification,&object:&nil)
在显示对话框之前,我们要冻结&好的&按钮
Objective-C版本:
okAction.enabled&=&NO;
swift版本:
okAction.enabled&=&false
接下来,在通知观察者(notification observer)中,我们需要在激活按钮状态前检查&登录&文本框的内容。
Objective-C版本:
-&(void)alertTextFieldDidChange:(NSNotification&*)notification{
&&&&UIAlertController&*alertController&=&(UIAlertController&*)self.presentedViewC
&&&&if&(alertController)&{
&&&&&&&&UITextField&*login&=&alertController.textFields.firstO
&&&&&&&&UIAlertAction&*okAction&=&alertController.actions.lastO
&&&&&&&&okAction.enabled&=&login.text.length&&&2;
swift版本:
func&alertTextFieldDidChange(notification:&NSNotification){
&&&&var&alertController&=&self.presentedViewController&as&UIAlertController?
&&&&if&(alertController&!=&nil)&{
&&&&&&&&var&login&=&alertController!.textFields?.first&as&UITextField
&&&&&&&&var&okAction&=&alertController!.actions.last&as&UIAlertAction
&&&&&&&&okAction.enabled&=&countElements(login.text)&&&2
UIAlertController的登录和密码对话框示例
好了,现在对话框的&好的&按钮被冻结了,除非在&登录&文本框中输入3个以上的字符:
当需要给用户展示一系列选择的时候(选择恐惧症患者杀手),上拉菜单就能够派上大用场了。和对话框不同,上拉菜单的展示形式和设备大小有关。在iPhone上(紧缩宽度),上拉菜单从屏幕底部升起。在iPad上(常规宽度),上拉菜单以弹出框的形式展现。
创建上拉菜单的方式和创建对话框的方式非常类似,唯一的区别是它们的形式。
Objective-C版本:
UIAlertController&*alertController&=&[UIAlertController&alertControllerWithTitle:@"保存或删除数据"&message:@"删除数据将不可恢复"&preferredStyle:&UIAlertControllerStyleActionSheet];
swift版本:
var&alertController&=&UIAlertController(title:&"保存或删除数据",&message:&"删除数据将不可恢复",&preferredStyle:&UIAlertControllerStyle.ActionSheet)
添加按钮动作的方式和对话框相同。
Objective-C版本:
UIAlertAction&*cancelAction&=&[UIAlertAction&actionWithTitle:@"取消"&style:UIAlertActionStyleCancel&handler:nil];
UIAlertAction&*deleteAction&=&[UIAlertAction&actionWithTitle:@"删除"&style:UIAlertActionStyleDestructive&handler:nil];
UIAlertAction&*archiveAction&=&[UIAlertAction&actionWithTitle:@"保存"&style:UIAlertActionStyleDefault&handler:nil];
[alertController&addAction:cancelAction];
[alertController&addAction:deleteAction];
[alertController&addAction:archiveAction];
swift版本:
var&cancelAction&=&UIAlertAction(title:&"取消",&style:&UIAlertActionStyle.Cancel,&handler:&nil)
var&deleteAction&=&UIAlertAction(title:&"删除",&style:&UIAlertActionStyle.Destructive,&handler:&nil)
var&archiveAction&=&UIAlertAction(title:&"保存",&style:&UIAlertActionStyle.Default,&handler:&nil)
alertController.addAction(cancelAction)
alertController.addAction(deleteAction)
alertController.addAction(archiveAction)
您不能在上拉菜单中添加文本框,如果您强行作死添加了文本框,那么就会荣幸地得到一个运行时异常:
* Terminating app due to uncaught exception &NSInternalInconsistencyException&, reason: &Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert&
同样,简单的异常说明,我们也不多说了。
接下来我们就可以在iPhone或者其他紧缩宽度的设备上展示了,不出我们所料,运行得很成功。
Objective-C版本:
[self&presentViewController:alertController&animated:YES&completion:nil];
swift版本:
self.presentViewController(alertController,&animated:&true,&completion:&nil)
iPhone上的上拉菜单效果
如果上拉菜单中有&取消&按钮的话,那么它永远都会出现在菜单的底部,不管添加的次序是如何(就是这么任性)。其他的按钮将会按照添加的次序从上往下依次显示。《iOS 用户界面指南》要求所有的&毁坏&样式按钮都必须排名第一(红榜嘛,很好理解的,对不对?)。
别激动得太早,我们现在还有一个很严重的问题,这个问题隐藏得比较深。当我们使用iPad或其他常规宽度的设备时,就会得到一个运行时异常:
Terminating app due to uncaught exception &NSGenericException&, reason: &UIPopoverPresentationController (&_uialertcontrolleractionsheetregularpresentationcontroller: 0x7fc=""&) should have a non-nil sourceView or barButtonItem set before the presentation occurs.&
就如我们之前所说,在常规宽度的设备上,上拉菜单是以弹出框的形式展现。弹出框必须要有一个能够作为源视图或者栏按钮项目的描点(anchor point)。由于在本例中我们是使用了常规的UIButton来触发上拉菜单的,因此我们就将其作为描点。
在iOS 8中我们不再需要小心翼翼地计算出弹出框的大小,UIAlertController将会根据设备大小自适应弹出框的大小。并且在iPhone或者紧缩宽度的设备中它将会返回nil值。配置该弹出框的代码如下:
Objective-C版本:
UIPopoverPresentationController&*popover&=&alertController.popoverPresentationC
if&(popover){
&&&&popover.sourceView&=&
&&&&popover.sourceRect&=&sender.
&&&&popover.permittedArrowDirections&=&UIPopoverArrowDirectionA
swift版本:
var&popover&=&alertController.popoverPresentationController
if&(popover&!=&nil){
&&&&popover?.sourceView&=&sender
&&&&popover?.sourceRect&=&sender.bounds
&&&&popover?.permittedArrowDirections&=&UIPopoverArrowDirection.Any
iPad上的上拉菜单效果
UIPopoverPresentationController类同样也是在iOS 8中新出现的类,用来替换UIPopoverController的。这个时候上拉菜单是以一个固定在源按钮上的弹出框的形式显示的。
要注意UIAlertController在使用弹出框的时候自动移除了取消按钮。用户通过点击弹出框的外围部分来实现取消操作,因此取消按钮便不再必需。
释放对话框控制器
通常情况下,当用户选中一个动作后对话框控制器将会自行释放。不过您仍然可以在需要的时候以编程方式释放它,就像释放其他视图控制器一样。您应当在应用程序转至后台运行时移除对话框或者上拉菜单。假定我们正在监听UIApplicationDidEnterBackgroundNotification通知消息,我们可以在observer中释放任何显示出来的视图控制器。(参考在viewDidLoad方法中设立observer的示例代码)。
Objective-C版本:
-&(void)didEnterBackground:(NSNotification&*)notification
&&[[NSNotificationCenter&defaultCenter]&removeObserver:self&name:UITextFieldTextDidChangeNotification&object:nil];
&&[self.presentedViewController&dismissViewControllerAnimated:NO&completion:nil];
swift版本:
func&didEnterackground(notification:&NSNotification){
&&&&NSNotificationCenter.defaultCenter().removeObserver(self,&name:&UITextFieldTextDidChangeNotification,&object:&nil)
&&&&self.presentedViewController?.dismissViewControllerAnimated(false,&completion:&nil)
注意,要保证运行安全我们同样要确保移除所有的文本框observer。
我们来总结一下
这篇文章比较长,但是希望能够对您有所帮助。原先的UIAlertView和UIActionSheet类仍然可以在iOS 8中工作得很好,所以没有必要急于更换代码(要知道本文用到的许多函数尽在iOS 8中支持)。本文的代码可以在我的Github主页上找到,包括了AlertController - ObjC以及AlertController - swift。
暂无相关文章
相关搜索:
相关阅读:
相关频道:
IOS教程最近更新

我要回帖

 

随机推荐