混淆可可问题ߞ除非存在无法识别的方法调用,否则程序将挂起

发布于 2024-09-11 11:08:40 字数 1988 浏览 4 评论 0原文

请耐心等待,这个问题很难解释。我希望那里的某个英雄知道这里发生了什么。需要一些历史;

我的一个可可物体“球”代表一个小图形。它仅在视图内才有意义。在 Ball 的某些方法中,它要求视图重绘。最重要的是,只要设置了球的位置参数,它就会要求视图重绘。这是在设置器中实现的。

这是建议的内容:

In View.m

- (void)mouseUp:(NSEvent *)theEvent {
    if (![runnerPath isEmpty]) {
        [walkPath removeAllPoints];
        [walkPath appendBezierPath:runnerPath];
        [runnerPath removeAllPoints];

        [[self held] setStep:0];
        [[self held] setPath:walkPath];
        [NSTimer scheduledTimerWithTimeInterval:.01 target:[self held] selector:@selector(pace) userInfo:nil repeats:YES];

        }
}

In Ball.m

 - (void)pace { 
    CGFloat juice = 10;
    BOOL loop = YES;

    while (loop) {
        if ([self step] == [[self path] elementCount]) {
            if ([[self timer] isValid]) {
                [[self timer] invalidate];
            }
            [[self path] removeAllPoints];
//          @throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]);
        }

        if (loop) {
            CGFloat distance;
            NSPoint stepPoint;

            if ([[self path] elementCount] > 0) {
                NSPoint returnPoints[2];
                [[self path] elementAtIndex:[self step] associatedPoints:returnPoints];
                stepPoint = returnPoints[0];
                distance = pixelDistance([self position], stepPoint);
            }

            if (distance <= juice) {
                [self setPosition:stepPoint];
                if (distance < juice) {
                    juice -= distance;
                    loop = YES;
                    [self setStep:[self step]+1];
                } else {
                    loop = NO;
                }
            } else {            
                NSPoint cutPoint = moveAlongBetween([self position], stepPoint, juice);
                [self setPosition:cutPoint];

                loop = NO;
            }

        }
    }

}

Bear with me, this one is hard to explain. I hope some hero out there knows what’s going on here. Some history needed;

One of my cocoa objects, “Ball” represents a small graphic. It only makes sense within a view. In some of the Ball’s methods, it asks the view to redraw. Most importantly, it asks the view to redraw whenever the Ball’s position parameter is set. This is achieved in the setter.

Here’s the mouthful, as suggested:

In View.m

- (void)mouseUp:(NSEvent *)theEvent {
    if (![runnerPath isEmpty]) {
        [walkPath removeAllPoints];
        [walkPath appendBezierPath:runnerPath];
        [runnerPath removeAllPoints];

        [[self held] setStep:0];
        [[self held] setPath:walkPath];
        [NSTimer scheduledTimerWithTimeInterval:.01 target:[self held] selector:@selector(pace) userInfo:nil repeats:YES];

        }
}

In Ball.m

 - (void)pace { 
    CGFloat juice = 10;
    BOOL loop = YES;

    while (loop) {
        if ([self step] == [[self path] elementCount]) {
            if ([[self timer] isValid]) {
                [[self timer] invalidate];
            }
            [[self path] removeAllPoints];
//          @throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]);
        }

        if (loop) {
            CGFloat distance;
            NSPoint stepPoint;

            if ([[self path] elementCount] > 0) {
                NSPoint returnPoints[2];
                [[self path] elementAtIndex:[self step] associatedPoints:returnPoints];
                stepPoint = returnPoints[0];
                distance = pixelDistance([self position], stepPoint);
            }

            if (distance <= juice) {
                [self setPosition:stepPoint];
                if (distance < juice) {
                    juice -= distance;
                    loop = YES;
                    [self setStep:[self step]+1];
                } else {
                    loop = NO;
                }
            } else {            
                NSPoint cutPoint = moveAlongBetween([self position], stepPoint, juice);
                [self setPosition:cutPoint];

                loop = NO;
            }

        }
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水波映月 2024-09-18 11:08:40

你能告诉我你是如何处理异常的吗?因为通常无法识别的选择器将结束您的程序。也许您需要一个异常而不是一个无法识别的选择器。尝试:

@throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]);

如果这也能解决问题,那么您将在这段代码之后执行一些操作,从而冻结应用程序。

编辑:感谢您的代码更新。

这里发生了一些奇怪的事情!我不打算重写整个事情,所以这里有一些提示:

  • 首先:您正在从计时器循环调用的某个例程中循环。这是故意的吗?无法在 while() 循环中暂停执行,因此无论如何它都会在一眨眼的时间内发生。您需要在类中保留一些状态信息。例如,每次调用 pace 时添加一个循环计数器。
  • 第二:如果您启动计时器,它将以计时器作为参数调用您的选择器。因此,将函数定义为 -(void)pace:(NSTimer*)timer,并使用 timer,而不是 [self timer] (后者无论如何,如果你不指定它,它就不会成为你的计时器!)
  • 第三:你每秒发射 100 次。这是很多,并且可能比您为其编写此代码的任何设备的刷新率都要高。我认为20/秒就足够了。
  • 第四:可以肯定的是,如果你将其更改为 -(void)pace:(NSTimer*)timer,不要忘记使用 @selector(pace:) (即不要忘记 :)

修复这些问题,如果仍然损坏,请再次更新您的问题并发表评论,以便我们知道。祝你好运!

could you also tell how you handle exceptions? since normally an unrecognized selector will end your program. Maybe you need an exception rather than an unrecognized selector. Try:

@throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]);

If this would fix it as well, you're doing something after this code which freezes the app.

edit: thanks for the code update.

There's some weird stuff going on here! I'm not going to rewrite the whole thing, so here's some pointers:

  • first of all: you're looping inside some routine that is called from a timer loop. Is that intended? There is no way to pause execution within that while() loop, so it will happen in a blink anyway. You would need to keep some state information in the class. E.g. adding a loop counter every time pace is called.
  • second: if you start a timer, it will call your selector with the timer as an argument. So define the function as -(void)pace:(NSTimer*)timer, and use timer, not [self timer] (the latter will not be your timer anyway, if you don't assign it!)
  • third: you're firing 100 times a second. That is a lot, and presumably higher than the refresh rate of any device you're writing this for. I think 20/sec is enough.
  • fourth: to be sure, if you change it to -(void)pace:(NSTimer*)timer, don't forget to use @selector(pace:) (i.e. don't forget the :)

fix those things, and if it's still broken, update your question again and put in comment so we will know. Good luck!

无悔心 2024-09-18 11:08:40

尝试调用

for (NSView *each in [self views]) {
    ...
}

我假设 views 是一个数组,因此快速枚举直接应用于它,无需调用 allObjects.

其他几点。

  1. 您是否设置了 objc_exception_throw 的全局断点?这将适用于所有 Xcode 项目,并且非常有用,我很惊讶它没有默认设置。
  2. 您说您查看了控制台是否有错误。那么,我认为您没有在代码上设置断点并进入其中以查看执行到达该点时到底发生了什么?查看 Xcode 调试指南

Try calling

for (NSView *each in [self views]) {
    ...
}

I'm assuming that views is an array, so fast enumeration applies to it directly and there is no need to call allObjects.

A couple of other points.

  1. Have you set a Global breakpoint of objc_exception_throw? This will apply to all Xcode projects and is so useful I'm surprised it isn't set by default.
  2. You say you looked at the Console for errors. I take it, then, that you didn't set a breakpoint on the code and step into it to see exactly what is happening when your execution reaches that point? Have a look at the Xcode Debugging Guide
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文