UIPercentDrivenInteractiveTransition 无法在快速手势上完成动画

2024-01-22

我创建了一个交互式过渡。我的func animateTransition(transitionContext: UIViewControllerContextTransitioning)很正常,我拿到容器了UIView,我将两个相加UIViewControllers然后我在 a 中进行动画更改UIView.animateWithDuration(duration, animations, completion).

I add a UIScreenEdgePanGestureRecognizer到我的UIViewController。除非我进行非常快速的平移,否则效果很好。

在最后一种情况下,应用程序没有响应,仍然处于相同状态UIViewController(转换似乎不起作用)但后台任务正在运行。当我运行Debug View Hierarchy,我看到了新的UIViewController而不是前一个,以及前一个(至少它的UIView) 站在转换结束时应该所在的位置。

我做了一些打印和检查点,从中我可以说,当问题发生时,动画完成(我的那个animateTransition方法)未达到,所以我不能调用transitionContext.completeTransition完成或不完成转换的方法。

我也可以看到平底锅有时会从UIGestureRecognizerState.Began直接到UIGestureRecognizerState.Ended不经过UIGestureRecognizerState.Changed.

当它经过的时候UIGestureRecognizerState.Changed, both the translation and the velocity每个都保持相同UIGestureRecognizerState.Changed states.

EDIT :

这是代码:

animateTransition method

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    self.transitionContext = transitionContext

    let containerView = transitionContext.containerView()
    let screens: (from: UIViewController, to: UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)

    let parentViewController = presenting ? screens.from : screens.to
    let childViewController = presenting ? screens.to : screens.from

    let parentView = parentViewController.view
    let childView = childViewController.view

    // positionning the "to" viewController's view for the animation
    if presenting {
        offStageChildViewController(childView)
    }

    containerView.addSubview(parentView)    
    containerView.addSubview(childView)

    let duration = transitionDuration(transitionContext)

    UIView.animateWithDuration(duration, animations: {

        if self.presenting {
            self.onStageViewController(childView)
            self.offStageParentViewController(parentView)
        } else {
            self.onStageViewController(parentView)
            self.offStageChildViewController(childView)
        }}, completion: { finished in
            if transitionContext.transitionWasCancelled() {
                transitionContext.completeTransition(false)
            } else {
                transitionContext.completeTransition(true)
            }
    })
}

手势和手势处理程序:

weak var fromViewController: UIViewController! {
    didSet {
        let screenEdgePanRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: "presentingViewController:")
        screenEdgePanRecognizer.edges = edge
        fromViewController.view.addGestureRecognizer(screenEdgePanRecognizer)
    }
}

func presentingViewController(pan: UIPanGestureRecognizer) {
    let percentage = getPercentage(pan)

    switch pan.state {

    case UIGestureRecognizerState.Began:
        interactive = true
        presentViewController(pan)

    case UIGestureRecognizerState.Changed:
        updateInteractiveTransition(percentage)

    case UIGestureRecognizerState.Ended:
        interactive = false

        if finishPresenting(pan, percentage: percentage) {
            finishInteractiveTransition()
        } else {
            cancelInteractiveTransition()
        }

    default:
        break
    }
}

知道会发生什么吗?

EDIT 2:

以下是未公开的方法:

override func getPercentage(pan: UIPanGestureRecognizer) -> CGFloat {
    let translation = pan.translationInView(pan.view!)
    return abs(translation.x / pan.view!.bounds.width)
}

override func onStageViewController(view: UIView) {
    view.transform = CGAffineTransformIdentity
}

override func offStageParentViewController(view: UIView) {
    view.transform = CGAffineTransformMakeTranslation(-view.bounds.width / 2, 0)
}

override func offStageChildViewController(view: UIView) {
    view.transform = CGAffineTransformMakeTranslation(view.bounds.width, 0)
}

override func presentViewController(pan: UIPanGestureRecognizer) {
    let location = pan.locationInView((fromViewController as! MainViewController).tableView)
    let indexPath = (fromViewController as! MainViewController).tableView.indexPathForRowAtPoint(location)

    if indexPath == nil {
        pan.state = .Failed
        return
    }
    fromViewController.performSegueWithIdentifier("chartSegue", sender: pan)
}
  • 我删除了“over”添加行 => 没有修复它
  • I added updateInteractiveTransition in .Began, in .Ended,在两个 => 中都没有修复它
  • 我在我的视图层上打开了shouldRasterizetoViewController并让它一直开着 => 没有修复它

但问题是,为什么在做快速交互手势的时候,是不是响应不够快呢?

实际上,只要我的手指留得足够长,它就可以通过快速交互手势来工作。例如,如果我平移速度非常快,超过(比方说)1 厘米,那就没问题。如果我在小于 1 厘米的小表面(再说一遍)上快速平移,那就不行了

可能的候选者包括动画视图太复杂(或具有复杂的效果,如阴影)

我也想过一个复杂的观点,但我不认为我的观点真的很复杂。有一堆按钮和标签,自定义的UIControl作为分段的片段,图表(在控制器出现后加载)和 xib 被加载到 viewController 内。


好的,我刚刚创建了一个project https://github.com/nico75005/testTransition使用最少的类和对象才能触发问题。因此,要触发它,您只需从右向左快速而短暂地滑动即可。

我注意到它第一次工作非常容易,但是如果你第一次正常拖动视图控制器,那么触发它会变得更加困难(甚至不可能?)。在我的完整项目中,这并不重要。


当我诊断这个问题时,我注意到手势的更改和结束状态事件之前发生过animateTransition甚至跑了。所以动画在开始之前就被取消/完成了!

我尝试使用GCD动画同步队列来确保更新UIPercentDrivenInterativeTransition直到`animate之后才会发生:

private let animationSynchronizationQueue = dispatch_queue_create("com.domain.app.animationsynchronization", DISPATCH_QUEUE_SERIAL)

然后我有一个实用方法来使用这个队列:

func dispatchToMainFromSynchronizationQueue(block: dispatch_block_t) {
    dispatch_async(animationSynchronizationQueue) {
        dispatch_sync(dispatch_get_main_queue(), block)
    }
}

然后我的手势处理程序确保更改和结束状态通过该队列进行路由:

func handlePan(gesture: UIPanGestureRecognizer) {
    switch gesture.state {

    case .Began:
        dispatch_suspend(animationSynchronizationQueue)
        fromViewController.performSegueWithIdentifier("segueID", sender: gesture)

    case .Changed:
        dispatchToMainFromSynchronizationQueue() {
            self.updateInteractiveTransition(percentage)
        }

    case .Ended:
        dispatchToMainFromSynchronizationQueue() {
            if isOkToFinish {
                self.finishInteractiveTransition()
            } else {
                self.cancelInteractiveTransition()
            }
        }

    default:
        break
    }
}

所以,我有手势识别器.Began状态挂起该队列,并且我让动画控制器恢复该队列animationTransition(确保队列仅在该方法运行之后在手势继续尝试更新UIPercentDrivenInteractiveTransition object.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UIPercentDrivenInteractiveTransition 无法在快速手势上完成动画 的相关文章

  • SwiftUI DisclosureGroup 单独展开每个部分

    我正在使用 Foreach 和 DisclosureGroup 来显示数据 每个部分都可以展开 折叠 然而 它们都在同时扩展 折叠 如何单独展开 折叠每个部分 struct TasksTabView View State private v
  • 寻找可靠的方法来选择iPhone 13微距相机设备

    我正在使用 objc 开发一个应用程序 我必须选择 iPhone 13 Pro 和 13 Pro Max 中配备的新微距摄像头 目前 我在所有其他设备上选择我的相机 并剪掉此代码 AVCaptureDeviceDiscoverySessio
  • 如何在注销并重新登录后保存按钮状态?

    我有一个保存按钮 点击该按钮后 会将标签 quoteLabel 中的文本保存到 Firebase 中的用户帐户 然后该按钮将隐藏 并且取消保存按钮将不再隐藏 以便用户可以根据需要取消保存 这两个按钮都可以根据需要发布和删除数据 但是 如果我
  • 命令行工具中的框架问题

    在每个人开始向我扔其他堆栈溢出和论坛帖子之前 我把它们都看了 他们都没有帮忙 我有一个简单的 cmd 工具 名为swizzler并想要嵌入SwizzleSrc其中的框架 我已经遵循了所有教程并且堆栈溢出但没有运气 这就是我得到的 Build
  • 如何在ios开发中从mp3文件中提取元数据

    我正在开发一个带有云存储的 ios 音乐播放器 我需要提取音乐信息 如标题 艺术家 艺术作品 我有一个名为 playit 的操作 可以播放和暂停 mp3 文件 它还应该使用与 mp3 文件关联的元数据来填充一些 UILables 和 UII
  • iOS8 自签名证书已安装但仍不受信任

    由于我无法控制的原因 我需要使用自签名证书针对平台进行 iOS 开发 它是一个在 SAN 中具有特定 IP 地址的根证书 当证书安装在 OSX 系统帐户下时 所有浏览器现在将正常信任对给定 IP 地址的任何访问 通过电子邮件将同一证书发送到
  • 每次打开应用程序时,FileManager 的路径 URL 都不同[重复]

    这个问题在这里已经有答案了 我想在fileManager根路径中创建一个文件夹 但在创建之前 我想检查该文件夹是否存在 如果不存在 我将创建 否则将保留它 这是我使用的功能 public func isDirectoryExist path
  • 强制本地化图像或图像资产

    正如在这个问题中 如何强制 NSLocalizedString 使用特定语言 https stackoverflow com questions 1669645 how to force nslocalizedstring to use a
  • 将时间舍入到最接近的三十秒

    我有一个应用程序 它显示每 30 秒过期的数据 准确地说 在 h m s 11 30 00 11 30 30 11 31 00 等 我可以获得当前时间 但我不确定如何计算现在到最近的三十秒之间的时间 我发现的所有内容都是 Objective
  • 如何将 RGB 值转换为十六进制字符串 iOS swift

    我想将 RGB 值转换为十六进制字符串 我将十六进制转换为 RGB 如下所示 但反之亦然 func hexStringToRGB hexString String gt red CGFloat green CGFloat blue CGFl
  • AST 文件格式错误或损坏

    我有一个问题 我不知道为什么会发生这种情况 但很可能是因为我错误地按了 移动到垃圾箱 到某些系统框架 我收到一条错误消息 AST 文件格式错误或损坏 找不到 AST 文件引用的文件 Users username myProject Quar
  • 在 for 循环中为元组赋值

    struct MIDIPacket 中有一个 UInt8 的元组 正常的赋值是这样的 import CoreMIDI let packet MIDIPacket packet data 0 0x02 packet data 1 0x5f 等
  • tableView.cellForRowAtIndexPath(indexPath) 返回 nil

    我有一个循环遍历表视图的验证函数 问题是它在某个时刻返回 nil 单元格 for var section 0 section lt self tableView numberOfSections section for var row 0
  • 从应用程序打开/关闭 iPhone 的 Wifi

    我需要打开或关闭 iPhone 中的 wifi 有什么方法可以做到吗 还是被禁止了 私有框架 所有使用公共 SDK 编写的应用程序都经过沙箱处理 他们只能访问苹果认为可以在该沙箱中使用的属性和数据 恐怕 Wi fi 不在列表中 请看一下这个
  • 如何在复杂的层次结构中上下同步 CALayer 和 UIView 动画

    See 如何在整个层次结构中管理 CALayer 动画 https stackoverflow com questions 26917908 how to manage calayer animations throughout a hie
  • 在 Swift 中计算两个 CLLocation 点之间的方位角 [重复]

    这个问题在这里已经有答案了 我正在尝试计算仅 swift 代码中两个 CLLocation 点之间的方位 我遇到了一些困难 并假设这是一个非常简单的函数 堆栈溢出似乎没有列出任何内容 func d2r degrees Double gt D
  • 辅助功能标识符在 iOS 模拟器的辅助功能检查器中不可见

    我想使用辅助功能检查器来验证在模拟器 iOS 9 2 中运行的应用程序中的所有辅助功能标识符 辅助功能检查器能够返回多个辅助功能字段 但不能返回标识符 知道为什么以及如何我能看到它们吗 实际上有一种方法 克里斯 普林斯 Chris Prin
  • SwiftUI 自动调整底部工作表的大小

    SwiftUI 有很多底部工作表的示例 但是它们都指定了使用 GeometryReader 工作表可以增长到的某种类型的最大高度 我想要的是创建一个底部工作表 其高度仅与其中的内容一样高 我使用首选项键提出了下面的解决方案 但必须有更好的解
  • 出现错误:FT_Open_Face 失败:错误 2

    当我使用时出现以下错误CGContextDrawPDFPage context PDFPage 对于某些文件 有解决办法来解决这个问题吗 FT Open Face failed error 2 错误2看起来像errno2 这是 找不到文件
  • 如何在 Swift 中将所有 iOS 设备的标签水平居中

    我不知道如何使标签在图像视图中水平居中 标签说 You ve been here What would you rate us 我想要What would you rate us属于 You ve been here 我试图完成此操作的方法

随机推荐

  • LINQ 多对多关系:解决方案?

    到目前为止 LINQ 已经非常优雅 但是为了执行基本的 m2m 查询 它没有提供我可以立即看到的解决方案 更糟糕的是 虽然它适用于任何其他表关系 但 LINQ 没有在我的 m2m 表的类结构中提供关联 所以我可以做类似的事情 artwork
  • justify-items 如何在 display:block 元素上工作

    The MDN 文档 https developer mozilla org en US docs Web CSS justify items of justify items指出 在块级布局中 它在内联轴上对齐其包含块内的项目 现在 我认
  • 导航视图 Sencha Touch 2

    我在 Sencha Touch 2 中的 NavigationView 有问题 当我按下 后退 按钮时 我无法导航多个窗口 我使用 view push 和 view pop 进行导航 view js Ext define MyApp vie
  • 扫描目录中的所有文件并按文件类型返回计数

    我刚刚加入一家 IT 公司并开始使用 ColdFusion 我的经理希望我在 ColdFusion 中编写代码 将扫描任何目录 例如c cf 其中包含数百个文件 包括 jQuery 文件 cfm 文件等 并给出此类文件的计数 我们可以手动选
  • Android N 中的 Java 8 Stream API

    根据谷歌的介绍 http android developers blogspot de 2016 03 first preview of android n developer html 从 Android N 开始 Android API
  • 使用 MySQL 和 PHP 读取部分 json 数据

    我使用一个 CMS 它以 JSON 格式在 MySQL 中保存资源 在一张表中 与来自 MySQL 的正常数据一起 当我循环数据时 我得到一个数组 JSON 数据 但我需要在 JSON 数据中搜索XNCatnCode Trying to l
  • 果冻豆运行设备出现 Listactivity 错误(SPAN_EXCLUSIVE_EXCLUSIVE 跨度的长度不能为零)

    我的应用程序以启动画面启动 然后打开列表活动行 单击任何行将打开一个包含文本视图 两个按钮 其中一个打开无限图库 另一个打开自定义对话框 和菜单项 关于 首选项 的活动 出口 这个应用程序在姜面包上完美运行 但在运行果冻豆的 Galaxy
  • Cordova 2.0.0 中的 Phonegap 屏幕截图插件

    我已经从 github 设置了屏幕截图插件 位于此处 https github com phonegap phonegap plugins tree master Android Screenshot https github com ph
  • 计算 Graphite 中 groupByNode() 结果的百分比

    我有两组石墨系列 都是这种格式 第二组是相同的 只是它具有 x y 前缀而不是 a b a b ccc a1 hr a b ccc a2 hr a b ccc a3 hr a b ddd a1 hr a b ddd a4 hr 要按我使用的
  • 从具有 x、y 和 z 坐标的点生成网格

    Problem 从 3D 点 带有 x y 和 z 坐标 生成网格 我拥有的是 3D 空间中的点 带有 x y 和 z 坐标 您可以在图 1 中看到它 输出是图像 2 或图像 3 或图像 4 简而言之 它将是网格 如果我有网格 可以提供其材
  • 如何在Bootstrap中实现响应式、独立滚动的窗格?

    我正在开发一个网络应用程序 我希望在较大的屏幕上有两个独立的可滚动区域 左侧的主要内容区域和右侧的较小侧边栏 我已经成功地使用 CSS 实现了这样的布局absolute定位和overflow属性 请参阅这个 JSFiddle http js
  • 生成16 QAM信号

    我知道使用以下方法生成 QPSK 信号的方法 TxS round rand 1 N 2 1 QPSK symbols are transmitted symbols TxS TxS sqrt 1 round rand 1 N 2 1 上面的
  • 如何从 OptaPlanner 升级到 Timefold?

    我们将 OptaPlanner 分叉为 Timefold https timefold ai blog 2023 optaplanner fork 前一段时间 我们经常会收到这样的问题 Timefold 更改所有导入语句和依赖项 如何有效地
  • 如何获取 int (C#) 中的第一个数字?

    在 C 中 获取 int 中第一个数字的最佳方法是什么 我想出的方法是将int转为字符串 找到字符串的第一个字符 然后将其转回int int start Convert ToInt32 curr ToString Substring 0 1
  • 可以使用 PIG 读取的文件格式

    使用PIG可以读取哪些类型的文件格式 如何以不同的格式存储它们 假设我们有 CSV 文件 我想将其存储为 MXL 文件 如何做到这一点 每当我们使用 STORE 命令时 它都会创建目录并将文件存储为part m 00000 我如何更改文件名
  • 在 Emacs 中重复输入变量名的快速方法?

    我刚刚第 N 次输入这种代码 menu add item spamspamspam spamspamspam 我想知道是否有更快的方法 我想要类似于 yasnippet 镜子的行为 除了 我不想创建一个片段 参数顺序不同于 项目到项目 语言
  • 是否可以在 JavaScript 中侦听对象属性的更改?

    我正在开发一个复杂的网络界面 它主要是用 JavaScript 构建的 它基本上是一种 非常 大的形式 有很多部分 每个部分都是基于表单其他部分的选项构建的 每当这些选项发生更改时 新值都会记录在 注册表 类型对象中 并且其他部分也会相应地
  • Java 以编程方式从密钥/证书读取信息

    我正在尝试构建一个证书 密钥管理工具 但我不明白如何获取证书 密钥的 md5 指纹 例如 如果我在密钥库上使用 keytool 命令 我会获得 Keystore type JKS Keystore provider SUN Your key
  • 如何在 if-then 语句中设置某事发生的概率?

    我刚刚开始学习编码 我正在创建一个简单的界面 我在其中说一些话 它会用我设置的短语进行响应 例如 如果我说 如果命令中是 你还好吗 说话 不 这很简单 只是不适合我 我怎样才能改变它 让它有 50 的机会说 不 有 50 的机会说 是 谢谢
  • UIPercentDrivenInteractiveTransition 无法在快速手势上完成动画

    我创建了一个交互式过渡 我的func animateTransition transitionContext UIViewControllerContextTransitioning 很正常 我拿到容器了UIView 我将两个相加UIVie