【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记24 popovers弹窗

上几话中我们详细了解了几种segue,我们也了解到了多MVC模式的几种控制器,比如导航、选项卡和分栏,除了这三种多MVC的模式之外,还有一种popover,它跟其他三种不太一样。首先先来认识一下popover(弹窗)


你可以看到弹窗会有一个小箭头指向触发弹窗的地方:


它像一个白色的三角形。出了弹窗的区域是白色,其他区域都是灰色的,单击其他区域的唯一功能就是让弹窗消失。


说popover不同的原因是,它不是一个UIViewController。它通常是presentation controller来出现在屏幕上的。所以popover并不真的需要一个viewcontroller,它的view是这个MVC,它可以纯粹依靠presentation controller机制来做到这一点。

虽然它不是自己的viewcontroller,但是它依旧有所有的segue,用法并没有区别。我们刚才在示例中看到的弹窗是ipad上的效果,在iphone它被modal替代了,IOS自动为你配适的。但是如果你使用代理或者presentation controller,你可以影响这个配适。我们来看幻灯片:


绿色部分和其他segue没有什么区别,但是黄色这行我从viewcontroller 过渡到popover得presentationcontroller。当你设置自身为代理时,你能做些什么呢?



我们看到代理中有两个代理方法。第一个方法用来配适设备,默认iphone上全屏展示,如果你把它的返回值的风格设为none,表示不配适,那么它的弹窗会和iphone上一样。

弹窗的另外一个重点是尺寸,你可能需要用一种面向对象的方式,也就是系统调用的方式来询问MVC合适的尺寸是多少,这只是控制器的一个属性,你可以重写它:


下面来展示一个Demo,让我们的弹窗显示浏览历史,并且适应内容的尺寸。

我们回到Psychologist这个Demo中,在storyboard中给HappinessVeiwController右上角添加一个按钮History用来显示我们点击的按钮的值,这些值组成整数数组用来表达小人脸的开心程度。注意这个按钮不要用UIButton,用BarButtonItem,这是个轻量级的按钮,专门放置在导航栏或者工具栏上。


我们需要让这个按钮展示一个新的控制器,所以我们向storyboard中拖一个新的控制器,然后把History按钮和这个控制器连线,注意segue方式要选择popover present。


和其他segue一样,给Identifier命名,我们取名为Show Diagnostic History。

虽然现在控制器是空白的,但是我们已经可以运行了。我们创建一个UIViewController和这个控制器对应起来,取名为TextViewController。

在storyboard中拖一个text view到新控制器中,这个textview可以显示多行文本,设置它为不可编辑,但是可以选中,修改文本文字为24号。你会在storyboard中看到textview中有很多文字,这些是占位文字,没有关系我们会在运行的时候重新写值,这些占位文字是不会显示的。


我们在代码中创建多行文本的outlet。

import UIKitclass TextViewController: UIViewController {@IBOutlet weak var textView: UITextView!{didSet{textView.text = text}}var text:String = ""{didSet{textView?.text = text}}
}

现在该为我们的segue做些准备了。那么这些准备工作应该在哪里做呢?显然我们不应该在HappinessViewController中做,因为这个控制器你可能是从别处拷贝来的,它的设计者希望它是专门用来管理笑脸的,它应该对浏览历史一无所知。那么我们该如何做呢?答案是创建一个新的控制器,然后继承HappinessViewController,再在其中增加浏览历史的功能。

import UIKitclass DiagonsedHappinessViewController: HappinessViewController {}

那么现在回到storyboard中,笑脸的类应该不再是HappinessViewController了,而是我们刚刚修改的新的类。



我们之前设置的各种outlet不会有问题,因为它是子类,继承了父类的所有东西,包括outlet。这就是控制器的多态性,通常你会有一个可重用的控制器,也许你想给某个特定的控制器中增加功能,这样你就可以创建它的子类。

import UIKitclass DiagonsedHappinessViewController: HappinessViewController {override var happiness:Int{didSet{diagnostHistory += [happiness]}}var diagnostHistory = [Int]()private struct History{static let SegueIdentifier = "Show Diagnostic History"}override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {if let identifier = segue.identifier{switch identifier{case History.SegueIdentifier:if let tcv = segue.destinationViewController as? TextViewController{tcv.text = "\(diagnostHistory)"}default:break}}}}


我们重写了属性happiness,这里的属性观察器和父类中的观察器不会冲突,程序会先执行父类中happiness的观察器运行你会发现这个记录只能记录上一次的点击记录,这是因为我们之前讲过的使用segue每次打开的MVC都是新创建的,所以这个浏览记录需要存在我们之前讲过的NSUserDefaults中。我们把diagnosticHistory改成计算属性,靠它读取或者写入NSDuserDefaults。

新的代码:

import UIKitclass DiagonsedHappinessViewController: HappinessViewController {override var happiness:Int{didSet{diagnostHistory += [happiness]}}private let defaults = NSUserDefaults.standardUserDefaults()var diagnostHistory:[Int]{get{return defaults.objectForKey(History.DefaultsKey) as? [Int] ?? []}set{defaults.setObject(newValue, forKey: History.DefaultsKey)}}private struct History{static let SegueIdentifier = "Show Diagnostic History"static let DefaultsKey = "DiagnosedHappinessViewController.History"}override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {if let identifier = segue.identifier{switch identifier{case History.SegueIdentifier:if let tcv = segue.destinationViewController as? TextViewController{tcv.text = "\(diagnostHistory)"}default:break}}}}

来运行一下看看,我们看到在iphone6上虽然出现了浏览记录,但是popover依旧会布满屏幕,下一个任务是修改它的尺寸了。


首先我们需要让我们的控制器可以作为自己的弹窗代理,所以:

class DiagonsedHappinessViewController: HappinessViewController,UIPopoverControllerDelegate 

然后如我们之前讲的,在segue中做处理,把原来的语句修改如下:

 case History.SegueIdentifier:if let tvc = segue.destinationViewController as? TextViewController,let ppc = tvc.popoverPresentationController {ppc.delegate = selftvc.text = "\(diagnostHistory)"}

可以看到popoverPresentationController是在UIViewController中的,只当这个MVC真的在一个弹窗中的时候它才会返回,否则返回nil,然后我们把代理设为自己,这是我们第一次控制系统的代理。之后我们实现控制尺寸的代理方法;

    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!, traitCollection: UITraitCollection!) -> UIModalPresentationStyle {return UIModalPresentationStyle.None}

这个代理的返回表示我们不做任何配适,运行看看:


完整代码如下:

import UIKitclass DiagonsedHappinessViewController: HappinessViewController,UIPopoverPresentationControllerDelegate{override var happiness:Int{didSet{diagnostHistory += [happiness]}}private let defaults = NSUserDefaults.standardUserDefaults()var diagnostHistory:[Int]{get{return defaults.objectForKey(History.DefaultsKey) as? [Int] ?? []}set{defaults.setObject(newValue, forKey: History.DefaultsKey)}}private struct History{static let SegueIdentifier = "Show Diagnostic History"static let DefaultsKey = "DiagnosedHappinessViewController.History"}override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {if let identifier = segue.identifier{switch identifier{case History.SegueIdentifier:if let tvc = segue.destinationViewController as? TextViewController,let ppc = tvc.popoverPresentationController {ppc.delegate = selftvc.text = "\(diagnostHistory)"}default:break}}}func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!, traitCollection: UITraitCollection!) -> UIModalPresentationStyle {return UIModalPresentationStyle.None}}

现在还有最后一个步骤,弹窗的窗口有点大,我们需要它的尺寸适应弹窗中的内容的大小。这次我们需要到TextViewController中去做修改:

 override var preferredContentSize:CGSize {get{if textView != nil && presentingViewController != nil{//presentationViewController也是父类的属性,表示当前显示的页面return textView.sizeThatFits(presentingViewController!.view.bounds.size)} else {return super.preferredContentSize //无论如何要考虑所有情况}}set{super.preferredContentSize = newValue}}

我们重写父类中的这个属性

然后再次运行:


成功了!



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React Native之didFocus和didBlur

1 didFocus和didBlur解释 didFocus - the screen focused (if there was a transition, the transition completed)didBlur - the screen unfocused (if there was a transition, the transition completed) didFocus是指当前页面第一次加载的时候会调用一次 didBlur是指当前…

python语法详解_解析 Python3 基础语法

行与缩进 python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} 。 缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。实例如下: if True: print ("True") else: print ("False") Color…

ASP.NET 6 中间件 - 介绍与基础

这是一个关于 .NET 6 中间件的系列文章。在这个系列中,我们将了解到什么是中间件,它能够做什么,以及我们为什么要使用它,并演示几种不同类型的中间件的实现。之后,我们会进一步了解中间件所在的管道,以及如…

数组的迭代数组里面每个对象添加属性值_JS数组和对象循环遍历的几种实现方式...

数组遍历1. 普通for循环let arr [1,2,3,4,5] for (let i 0; i < arr.length; i) {console.log(arr[i]) } // 输出结果 // 1 // 2 // 3 // 4 // 52. 优化普通for循环let arr [1,2,3,4,5] for(var j 0,len arr.length; j < len; j){console.log(arr[j]); }3. forEach循…

Blend4精选案例图解教程(三):一键拖拽

原文:Blend4精选案例图解教程&#xff08;三&#xff09;&#xff1a;一键拖拽拖拽效果&#xff0c;常规实现方法是定义MoveLeftDwon、MoveLeftUp、MouseMove事件&#xff0c;在Blend的世界里&#xff0c;实现对象的拖拽&#xff0c;可以不写一行代码&#xff0c;而且非常简单&…

python画气泡图_​用Python把图做的好看点:用Matplotlib画个好看的气泡图

我们继续来把简单的图形丢到极坐标&#xff0c;这次是气泡图和柱状图&#xff0c;临摹的对象是澎湃美数课这个图看起来很好看&#xff0c;原理其实很简单&#xff0c;把柱状图和气泡图从笛卡尔坐标系中转移到极坐标系中来就OK 我们开始本次的临摹吧 本期的主题如下&#xff1a;…

Asp.NET Core一个接口的多个实现如何基于当前HTTP请求注册

前言假设我们有三个Service类实现了同一接口&#xff0c;示例代码如下&#xff1a;public interface IService { } public class ServiceA : IService { } public class ServiceB : IService { } public class ServiceC : IService { }我们希望在运行时使用依赖注入指定其具体…

pytorch forward_【Pytorch部署】TorchScript

TorchScript是什么&#xff1f;TorchScript - PyTorch master documentation​pytorch.orgTorchScript是一种从PyTorch代码创建可序列化和可优化模型的方法。任何TorchScript程序都可以从Python进程中保存&#xff0c;并加载到没有Python依赖的进程中。我们提供了一些工具来增量…

兼容ie8 rgba()用法

今天遇到了一个问题&#xff0c;要在一个页面中设置一个半透明的白色div。这个貌似不是难题&#xff0c;只需要给这个div设置如下的属性即可&#xff1a; background: rgba(255,255,255,.1); 但是要兼容到ie8。这个就有点蛋疼了。因为ie8不支持rgba()函数。下面我们总结一下rgb…

python中的标识符能不能使用关键字_Python中的标识符不能使用关键字

Python中的标识符不能使用关键字答&#xff1a;√智慧职教: 检查客室座椅外观良好&#xff0c;确认?无破损答&#xff1a;坐垫 靠背关于投标报价时综合单价的确定&#xff0c;下列做法中正确的是()答&#xff1a;以项目特征描述为依据确定综合单价城市总体规划调查时&#xff…

C# WPF实战项目升级了

概述之前用Caliburn.Micro搭建的WPF实战项目&#xff0c;CM框架选用了 3.0.3&#xff0c;实际上CM框架目前最新版已经到4.0。173了&#xff0c;所有很有必须升级一下项目了. 本来打算把平台框架也直接升级到.NET 6 的&#xff0c;但是项目里面很多库不支持最新的平台版本&#…

ArcGIS Engine开发模板及C#代码

目 录 1. 模板 2. 代码 1. 模板 以下为AE开发软件自带的模板及代码,开发工具为VS 2012+ArcGIS Engine 10.2。 2. 代码 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; us…

高级iOS面试题

非标准答案 2 1: 类方法是可以直接通过类名直接调用&#xff0c;无需进行实例化对象。类方法是以开头2. 实例方法&#xff0c;需要显示实例化对象&#xff0c;为对象分配堆栈空间&#xff0c;并通过对象实例调用实例方法3. RUNTIME 是在程序运行过程动态对实例对象进行操作&…

dotTrace 6.1帮你理解SQL查询如何影响应用性能

dotTrace是JetBrains公司旗下的一款.NET应用程序性能瓶颈检测工具。该工具是ReSharper旗舰版的一部分&#xff0c;也可以单独安装。近日&#xff0c;dotTrace 6.1发布&#xff0c;主要增加了人们期待已久的SQL查询性能分析&#xff0c;开发人员可以通过它获得特定查询的执行时间…

mysql申请审核系统_Mysql审核工具archery

Mysql审核工具archery系统&#xff1a;Centos6.8ip:192.168.122.150安装Python和virtualenv编译安装[rootwww ~]# yum install wget gcc make zlib-devel openssl openssl-devel[rootwww src]# wget "https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tar.xz"[…

iOS——Core Animation 知识摘抄(二)

阴影 主要是shadowOpacity 、shadowColor、shadowOffset和shadowRadius四个属性 shadowPath属性 我们已经知道图层阴影并不总是方的&#xff0c;而是从图层内容的形状继承而来。这看上去不错&#xff0c;但是实时计算阴影也是一个非常消耗资源的&#xff0c;尤其是图层有多个子…

Blazor University (11)组件 — 替换子组件的属性

原文链接&#xff1a;https://blazor-university.com/components/replacing-attributes-on-child-components/替换子组件的属性源代码[1]到目前为止&#xff0c;我们已经了解了如何创建代码生成的属性[2]&#xff0c;以及如何捕获意外参数[3]。除了这两种技术之外&#xff0c;B…

HTTPS实现原理

HTTPS实现原理 HTTPS&#xff08;全称&#xff1a;Hypertext Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;是以安全为目标的HTTP通道&#xff0c;简单讲是HTTP的安全版。即HTTP下加入SSL层&#xff0c;HTTPS的安全基础是SSL。其所用的端口号是443。…

C#使用ServiceController控制windows服务

C#中,使用ServiceController类控制windows服务,使用之前要先添加引用:System.ServiceProcess,然后在命名空间中引用:using System.ServiceProcess。下面举例获取本机的所有已安装的Windows服务和应用,然后查找某一应用活服务是否已经安装。 代码: using System; using S…

电信aep平台是什么意思_江苏天鼎证券:股票平台跳水是什么意思?股票为什么会跳水?...

相信很多新手在刚玩股票的时候会遇到很多的专业的基础知识不能理解&#xff0c;比如什么是跳水?为什么会跳水呢?接下来就为大家详细来说股票的跳水以及为何会跳水。一、股票平台跳水是什么意思?股票跳水通常指股价在较短的时间内&#xff0c;出现从高位下降到低位的现象。出…