草庐IT

ios - 在 CAKeyframeAnimation 中崩溃,用于沿路径对 View 进行动画处理

coder 2023-09-29 原文

我有一些代码可以为 UIView 设置动画:在沿路径设置动画的同时将其缩小。

它因以下错误而崩溃(可重现:总是):

CoreGraphics`CG::Path::apply(void*, void (*)(void*, CGPathElementType, CGPoint const*)) const:
0x1055c06:  pushl  %ebp
0x1055c07:  movl   %esp, %ebp
0x1055c09:  subl   $24, %esp
0x1055c0c:  movl   8(%ebp), %eax
0x1055c0f:  movl   (%eax), %ecx
0x1055c11:  movl   (%ecx), %eax
0x1055c13:  movl   16(%ebp), %edx
0x1055c16:  movl   %edx, 8(%esp)
0x1055c1a:  movl   12(%ebp), %edx
0x1055c1d:  movl   %edx, 4(%esp)
0x1055c21:  movl   %ecx, (%esp)
0x1055c24:  calll  *64(%eax)
0x1055c27:  addl   $24, %esp
0x1055c2a:  popl   %ebp
0x1055c2b:  ret    

认为它来自下面的方法(pathAnimationWithStartPoint:),好像我没有添加它返回的 CAKeyframeAnimation,即,只是:

[group setAnimations:@[ zoomAnimation ]];

代替

[group setAnimations:@[ zoomAnimation, pathAnimation ]];

它运行时不会崩溃。

- (CAKeyframeAnimation *) pathAnimationWithStartPoint:(CGPoint) startPoint {
    CGPoint endPoint = self.showApplicationTourButton.center;

    CGFloat xDistanceBetweenStartAndEndPoints = abs(startPoint.x - endPoint.x);
    CGFloat yOfHighestPointOfCurvePath = endPoint.y - 250;

    CGPoint controlPoint1 =  CGPointMake(startPoint.x + 1.0f / 3.0f * xDistanceBetweenStartAndEndPoints, yOfHighestPointOfCurvePath);
    CGPoint controlPoint2 = CGPointMake(startPoint.x + 2.0f / 3.0f * xDistanceBetweenStartAndEndPoints, yOfHighestPointOfCurvePath);

    CGMutablePathRef curvedPath = CGPathCreateMutable();

    CGPathMoveToPoint(curvedPath, NULL, startPoint.x, startPoint.y);
    CGPathAddCurveToPoint(curvedPath, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);


    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    pathAnimation.path = curvedPath;
    CGPathRelease(curvedPath);



    pathAnimation.calculationMode = kCAAnimationPaced;
    pathAnimation.fillMode = kCAFillModeForwards;
    pathAnimation.removedOnCompletion = NO;


    return pathAnimation;
}

回溯:

* thread #1: tid = 0x1a03, 0x01055c11 CoreGraphics`CG::Path::apply(void*, void (*)(void*, CGPathElementType, CGPoint const*)) const + 11, stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
    frame #0: 0x01055c11 CoreGraphics`CG::Path::apply(void*, void (*)(void*, CGPathElementType, CGPoint const*)) const + 11
    frame #1: 0x00f5d090 CoreGraphics`CGPathApply + 64
    frame #2: 0x01838c68 QuartzCore`CA::Render::Path::new_path(CGPath const*, bool) + 158
    frame #3: 0x018c3493 QuartzCore`-[CAKeyframeAnimation _setCARenderAnimation:layer:] + 176
    frame #4: 0x018c3b2c QuartzCore`-[CAKeyframeAnimation _copyRenderAnimationForLayer:] + 68
    frame #5: 0x018c6f12 QuartzCore`-[CAAnimationGroup _copyRenderAnimationForLayer:] + 241
    frame #6: 0x018df547 QuartzCore`CA::Layer::commit_animations(CA::Transaction*, double (*)(CA::Layer*, double, void*), void (*)(CA::Layer*, CA::Render::Animation*, void*), void (*)(CA::Layer*, void**, void*), void*) + 641
    frame #7: 0x01855520 QuartzCore`CA::Context::commit_layer(CA::Layer*, unsigned int, unsigned int, void*) + 94
    frame #8: 0x018d87fa QuartzCore`CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 330
    frame #9: 0x018d877e QuartzCore`CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 206
    frame #10: 0x01856667 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 1775
    frame #11: 0x01857227 QuartzCore`CA::Transaction::commit() + 395
    frame #12: 0x018f9b17 QuartzCore`+[CATransaction commit] + 52
    frame #13: 0x000399bf MyApp`-[HomeViewController catchTourScrollViewScreenshotViewAndAnimateItToButton](self=0x0b4e5210, _cmd=0x006f381a) + 1903 at HomeViewController.m:197
    frame #14: 0x0391f663 libobjc.A.dylib`-[NSObject performSelector:] + 62
    frame #15: 0x0003c383 MyApp`-[NSObject(self=0x0b4e5210, _cmd=0x006ef5ad, selector=0x006f381a) performSelectorIfRespondsToIt:] + 243 at NSObject+PerformSelectorIfRespondsToIt.m:22
    frame #16: 0x00042506 MyApp`__44-[TourViewController closeTourWithAnimation]_block_invoke268(.block_descriptor=0x0b6985a0, finished='\x01') + 86 at TourViewController.m:419
    frame #17: 0x01af0df6 UIKit`-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 223
    frame #18: 0x01ae3d66 UIKit`-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 237
    frame #19: 0x01ae3f04 UIKit`-[UIViewAnimationState animationDidStop:finished:] + 68
    frame #20: 0x12b6ff28 UIKit`-[UIViewAnimationStateAccessibility(SafeCategory) animationDidStop:finished:] + 66
    frame #21: 0x018df7d8 QuartzCore`CA::Layer::run_animation_callbacks(void*) + 284
    frame #22: 0x03a90014 libdispatch.dylib`_dispatch_client_callout + 14
    frame #23: 0x03a807d5 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 296
    frame #24: 0x03f3eaf5 CoreFoundation`__CFRunLoopRun + 1925
    frame #25: 0x03f3df44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #26: 0x03f3de1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #27: 0x044c67e3 GraphicsServices`GSEventRunModal + 88
    frame #28: 0x044c6668 GraphicsServices`GSEventRun + 104
    frame #29: 0x01aa5ffc UIKit`UIApplicationMain + 1211
    frame #30: 0x0000285d MyApp`main(argc=1, argv=0xbffff3f4) + 141 at main.m:16
    frame #31: 0x00002785 MyApp`start + 53
* thread #1: tid = 0x1a03, 0x01055c11 CoreGraphics`CG::Path::apply(void*, void (*)(void*, CGPathElementType, CGPoint const*)) const + 11, stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
    frame #0: 0x01055c11 CoreGraphics`CG::Path::apply(void*, void (*)(void*, CGPathElementType, CGPoint const*)) const + 11
    frame #1: 0x00f5d090 CoreGraphics`CGPathApply + 64
    frame #2: 0x01838c68 QuartzCore`CA::Render::Path::new_path(CGPath const*, bool) + 158
    frame #3: 0x018c3493 QuartzCore`-[CAKeyframeAnimation _setCARenderAnimation:layer:] + 176
    frame #4: 0x018c3b2c QuartzCore`-[CAKeyframeAnimation _copyRenderAnimationForLayer:] + 68
    frame #5: 0x018c6f12 QuartzCore`-[CAAnimationGroup _copyRenderAnimationForLayer:] + 241
    frame #6: 0x018df547 QuartzCore`CA::Layer::commit_animations(CA::Transaction*, double (*)(CA::Layer*, double, void*), void (*)(CA::Layer*, CA::Render::Animation*, void*), void (*)(CA::Layer*, void**, void*), void*) + 641
    frame #7: 0x01855520 QuartzCore`CA::Context::commit_layer(CA::Layer*, unsigned int, unsigned int, void*) + 94
    frame #8: 0x018d87fa QuartzCore`CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 330
    frame #9: 0x018d877e QuartzCore`CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 206
    frame #10: 0x01856667 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 1775
    frame #11: 0x01857227 QuartzCore`CA::Transaction::commit() + 395
    frame #12: 0x018f9b17 QuartzCore`+[CATransaction commit] + 52
    frame #13: 0x000399bf MyApp`-[HomeViewController catchTourScrollViewScreenshotViewAndAnimateItToButton](self=0x0b4e5210, _cmd=0x006f381a) + 1903 at HomeViewController.m:197
    frame #14: 0x0391f663 libobjc.A.dylib`-[NSObject performSelector:] + 62
    frame #15: 0x0003c383 MyApp`-[NSObject(self=0x0b4e5210, _cmd=0x006ef5ad, selector=0x006f381a) performSelectorIfRespondsToIt:] + 243 at NSObject+PerformSelectorIfRespondsToIt.m:22
    frame #16: 0x00042506 MyApp`__44-[TourViewController closeTourWithAnimation]_block_invoke268(.block_descriptor=0x0b6985a0, finished='\x01') + 86 at TourViewController.m:419
    frame #17: 0x01af0df6 UIKit`-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 223
    frame #18: 0x01ae3d66 UIKit`-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 237
    frame #19: 0x01ae3f04 UIKit`-[UIViewAnimationState animationDidStop:finished:] + 68
    frame #20: 0x12b6ff28 UIKit`-[UIViewAnimationStateAccessibility(SafeCategory) animationDidStop:finished:] + 66
    frame #21: 0x018df7d8 QuartzCore`CA::Layer::run_animation_callbacks(void*) + 284
    frame #22: 0x03a90014 libdispatch.dylib`_dispatch_client_callout + 14
    frame #23: 0x03a807d5 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 296
    frame #24: 0x03f3eaf5 CoreFoundation`__CFRunLoopRun + 1925
    frame #25: 0x03f3df44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #26: 0x03f3de1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #27: 0x044c67e3 GraphicsServices`GSEventRunModal + 88
    frame #28: 0x044c6668 GraphicsServices`GSEventRun + 104
    frame #29: 0x01aa5ffc UIKit`UIApplicationMain + 1211
    frame #30: 0x0000285d MyApp`main(argc=1, argv=0xbffff3f4) + 141 at main.m:16
    frame #31: 0x00002785 MyApp`start + 53

打开 NSZombie 不会提供任何更有用的调试信息。

在升级到 Xcode 4.6.3 (4H1503) 之前使用的相同代码。需要注意的是:在模拟器中,动画有时会暂停,点击它会恢复。这个奇怪的人工制品是出现问题的迹象,但我当时还不知道。

我错过了什么吗?
如果这是一个已知的错误,是否有任何解决方法?


一些研究笔记: similar question has been asked on SO ,但接受的答案只是通过将路径动画更改为线性平移来“解决”问题。

我的问题似乎也与此处的博文非常相似:http://www.blogosfera.co.uk/2013/08/exc_bad_access-while-using-coreanimation/

最佳答案

这真的不是什么答案,更多的是试图给你一个工具来寻找更多的线索。希望比我有更多线索的人会插话。

  • 打开 malloc 堆栈日志记录。
  • 重现崩溃。
  • 检查寄存器;如果 $r0 或 $r1 看起来像堆分配,则获取所述地址的 malloc 历史记录。

如果任一事件的最后一个事件是 FREE,则数据缓冲区(或对象)将被过早释放。 (有关获取 malloc 历史记录的信息,请参阅 http://lldb.llvm.org/lldb-gdb.html)。

现在,即使它确认这是一个过早的释放,它实际上可能不会帮助您那个。如果是这样,它会告诉你这是一个竞争条件。不幸的是,修复它实际上是不可能的,但可能有一种解决方法。如果您能弄清楚您控制的哪个对象可能已经分配了过早的 free()d 缓冲区,那么您应该能够持有对所述对象的强引用,直到动画完全完成。

请提交错误,附上崩溃的二进制文件。


此外,打开 malloc scribble。这将确保释放的内存在释放后立即被丢弃,这应该使崩溃尽快发生。

关于ios - 在 CAKeyframeAnimation 中崩溃,用于沿路径对 View 进行动画处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18448106/

有关ios - 在 CAKeyframeAnimation 中崩溃,用于沿路径对 View 进行动画处理的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  7. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  8. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  9. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  10. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

随机推荐