2

如果您想查看我遇到问题的代码,请点击以下链接: 代码

我的问题与我过去的问题有关

我的 确实有问题NSMutableArray,我目前正在iCarousel用于我的slotMachine对象(slot1 和 slot2)。我的应用程序是这样工作的:

PhotoViewController我制作了一个包含缩略图的视图,然后将其框架分配给按钮。因此,如果按下 1 个图像,它将通过NSUserDefaults. 然后我会在我的carouselViewController

我想调整阵列,但我不能。我也在这里尝试过我的问题: 与 NSMutableArray 比较 如果我能做到这一点,Array 2那将很容易,但仍然无法正常工作。

附加信息:)

我已经这样做了,有一个 Viewcontroller 包含 UIImageView 和一个按钮,所以当用户点击它时,我的CustomPicker弹出。MyCustomPicker包含用户在相机胶卷上选取的图像。所以每个按钮都有一个特定的值发送给我iCarouselViewusing NSUserDefaults。carousel1 用于第一个插槽,carousel2 用于第二个插槽。

这是我想做的:我想强制让它停止到用户选择的索引。(我在我做的carouselDidEndScrollingAnimtaion

在我的carouselDidEndScrollingAnimation方法中,我测试了我的所有条件(单独),它在比较方面非常有效。然后当我结合条件时,前两个比较或STOP是正确的,但后面两个总是错误的。或者有时搞混了。

我需要滚动用户选择的两个特定索引/整数(我已经这样做了)能够滚动其中的 2 对,但接下来的两个总是错误的,因为我认为索引正在调整。

图片:

下面的图片是我的PhotoViewController,其中包含我的游戏的比较阶段SETTINGUIImageVIew带有UIButton.Image的,将根据它输入的数字将被强制显示,并且应该强制显示。

在此处输入图像描述

当我的 iCarousel 启动时,它会在下图中停止(与上图不同): 在此处输入图像描述

将强制滚动到输入的图像中PhotoViewController

进入: 在此处输入图像描述

总结: 就是这样。我有一个settingsView从那里,我将为Slot1&导入我的图像(多个) Slot2。然后在另一个视图中PhotoViewController显示上面的图像。第一列对应于第一个插槽,然后是第二个插槽。如果按下视图(例如No. 1Slot 1它将加载图像的缩略图,加载从Picker.Slot 1

你必须做 4 次(对)----> 这里显示的我通过 NSUserDefaults 通过 button.tag 获取他们的索引,然后发送到iCarouselView.

然后当你完成(按下Done按钮)时,它会转到iCarouselViewthen,如上图所示,这就是它的视图。按下时它将旋转几秒钟,然后当完成但不停留在用户选择的位置时PhotoView,它将强制滚动到该索引。

问题:

有没有办法让我的数组或我的 iCarousel.view 在我删除时不调整它们的索引。仍然以正确的方式保留我的索引。或者是否有其他解决方案,比如调整我的数组,就像调整我PhotoViewController选择的索引一样。因为我认为当我的数组保留它们的索引时,即使删除我也能解决这个问题。但还是不行。

希望你能理解我的问题。

4

5 回答 5

1

很难知道这里的问题是什么。您是否对图像使用单个 NSMutableArray 并使用 NSUserDefaults 值来获取数组索引处的对象?

我不能 100% 确定正在发生的事情。用户做什么(以及在什么视图中)以及之后触发了什么(呈现哪个视图)。

您是否试图阻止图像上与从前一个视图中选取的图像相同的“旋转”图像?

根据您上面的图像,图像被一个索引关闭。每次都是这样吗?您从数组中提取可能存在问题。

如果您给我更多信息,我可以提供帮助。

我再次查看了您粘贴的代码,我认为这可能是您的问题

if (twoSlot1 > [(UIImageView*)[self.carousel2 currentItemView] tag]){            
                [self.carousel1 scrollToItemAtIndex:(-twoSlot1)-2 duration: 3.5f];
            } else {
                [self.carousel1 scrollToItemAtIndex:-twoSlot1 duration: 3.5f];
            }

在所有其他类似的代码块上,您都可以在其中调用每个轮播。在上面的代码中,您调用 carousel 1 两次。

if (slot2 > [(UIImageView*)[self.carousel1 currentItemView] tag]){
            [self.carousel1 scrollToItemAtIndex:(-slot2)-2 duration: 3.0f];
            } else {
            [self.carousel1 scrollToItemAtIndex:-slot2 duration: 3.0f];    
            }

            if (twoSlot2 > [(UIImageView*)[self.carousel2 currentItemView] tag]){
            [self.carousel2 scrollToItemAtIndex:(-twoSlot2)-2 duration: 3.5f];    
            } else {
            [self.carousel2 scrollToItemAtIndex:-twoSlot2 duration: 3.5f];
            }

当您应该呼叫号码 2 时,您呼叫 self.carousel1。

这个对吗?

于 2012-07-09T17:02:33.043 回答
1

参考你的问题。您需要一个在从数组中删除成员时不更改其成员索引的数组。

我想你可以使用 NSMutableDictionary。可以说它是一个关联数组,其中的索引是您选择的,当您从中间删除一个成员时,它们保持不变。您仍然可以使用 0..n 作为您的索引。你仍然可以使用一些你熟悉的 NSArray 中的方法,例如 count。您可以使用枚举器来遍历字典的所有成员。另一方面,你仍然可以使用你的 for 循环,因为你习惯于将它们与数组一起使用。只需准备好 a) objectForKey:i 如果键/索引不存在(例如被删除)可能会返回 nil,并且该计数会重新调整对象的数量,但不会像数组那样返回最高索引+1。

于 2012-07-13T08:40:37.753 回答
1

有没有办法让我的数组或我的 iCarousel.view 在我删除时不调整它们的索引。仍然以正确的方式保留我的索引。或者还有其他解决方案,比如调整我的数组,就像调整我的 PhotoViewController 选择的索引一样。因为我认为当我的数组保留它们的索引时,即使删除我也能解决这个问题。但还是不行。

您必须修改 iCarousel 管理其索引的方式的唯一方法是修改代码。实际上,如果您查看removeViewAtIndexiCarousel.m 中的方法,您会看到索引是通过 NSDictionary 管理的,并且在删除时,字典会重新排列(项目重新排序)。你可以采取这种方法:

- (void)removeViewAtIndex:(NSInteger)index
{
    NSMutableDictionary *newItemViews = [NSMutableDictionary dictionaryWithCapacity:[itemViews count] - 1];
    for (NSNumber *number in [self indexesForVisibleItems])
    {
        NSInteger i = [number integerValue];
        if (i < index)
        {
            [newItemViews setObject:[itemViews objectForKey:number] forKey:number];
        }
        else if (i > index)
        {
            [newItemViews setObject:[itemViews objectForKey:number] forKey:[NSNumber numberWithInteger:i - 1]];
        }
    }
    self.itemViews = newItemViews;
}

您可以对阵列应用相同的逻辑,以便轮播和阵列保持同步。当然,如果您将索引存储在某处(slot1/slot2/slot2/slot4?),您还应该在删除元素后更新它们的值。

另一方面,我认为您在这里要问的是如何做一些您认为可以解决您遇到的问题的事情,但您并没有真正解释问题是什么。事实上,如果我理解正确,你所做的是:

  1. 旋转旋转木马;

  2. 当轮播停止时,如果它不是偶然出现在所需的项目上,则“强制”它滚动到该项目。

没有理由在删除某些元素后这不应该工作(除非 iCarousel 有一些错误,那么解决方案就是捕捉错误)。唯一的部分是知道您想要移动到哪个索引。

作为建议,我将从简化您的委托carouselDidEndScrollingAnimation方法开始。确实,您carouselDidEndScrollingAnimation有一个名为 的参数carousel,我认为这是您在该方法中应该引用的唯一轮播。如果你没有看到它,这就是推理:你的每个轮播将停止滚动并且carouselDidEndScrollingAnimation将被调用;这样该方法将被调用两次。每次执行该方法时,您都将修改 carousel1 和 carousel2 的状态(通过调用scrollToItemAtIndex);因此,在每个轮播上,您将调用scrollToItemAtIndex两次。

这对我来说听起来不太正确。因此,您应该找到一种方法,在 carousel1carouselDidEndScrollingAnimation调用时仅滚动 carousel1,而在 carousel2 调用时仅滚动carouselDidEndScrollingAnimationcarousel2。

更一般地说,我想提出的另一点是:

  1. 让旋转木马停下来;

  2. 再次滚动它以使其到达所需位置;

似乎不是最好的实现,因为用户会看到轮播停止然后重新开始。

我解决这个问题的方法是直接修改 iCarousel 实现,以便它支持您需要的这种特定行为。

具体看一下stepiCarousel.m中的方法。这在每一帧被调用以产生轮播动画。现在,在这个方法中有一个decelerating分支:

else if (decelerating)
{
    CGFloat time = fminf(scrollDuration, currentTime - startTime);
    CGFloat acceleration = -startVelocity/scrollDuration;
    CGFloat distance = startVelocity * time + 0.5f * acceleration * powf(time, 2.0f);
    scrollOffset = startOffset + distance;

    [self didScroll];
    if (time == (CGFloat)scrollDuration)
    {
        decelerating = NO;
        if ([delegate respondsToSelector:@selector(carouselDidEndDecelerating:)])
        {
            [delegate carouselDidEndDecelerating:self];
        }
        if (scrollToItemBoundary || (scrollOffset - [self clampedOffset:scrollOffset]) != 0.0f)
        {
            if (fabsf(scrollOffset/itemWidth - self.currentItemIndex) < 0.01f)
            {
                //call scroll to trigger events for legacy support reasons
                //even though technically we don't need to scroll at all
                [self scrollToItemAtIndex:self.currentItemIndex duration:0.01];
            }
            else
            {
                [self scrollToItemAtIndex:self.currentItemIndex animated:YES];
            }
        }
        else
        {
            CGFloat difference = (CGFloat)self.currentItemIndex - scrollOffset/itemWidth;
            if (difference > 0.5)
            {
                difference = difference - 1.0f;
            }
            else if (difference < -0.5)
            {
                difference = 1.0 + difference;
            }
            toggleTime = currentTime - MAX_TOGGLE_DURATION * fabsf(difference);
            toggle = fmaxf(-1.0f, fminf(1.0f, -difference));
        }
    }
}

您会看到,当轮播停止减速时,它会再次滚动。这与您所做的完全相同,因此您可能会找到一种方法来修改此代码并使轮播精确地滚动到您需要的索引。通过这种方式,您将获得更顺畅的旋转木马旋转。

希望这有助于并为冗长的回复道歉。

于 2012-07-12T20:30:15.383 回答
0

我很难理解你的整体问题,但我可以收集到你问题的症结在于:

有没有办法让我的数组或我的 iCarousel.view 在我删除时不调整它们的索引。

我不知道它是否会解决您更大的问题,但是使用 NSMutableDictionary 来模拟数组应该允许您这样做。您可以简单地将索引用作字典的键,然后当您删除与索引关联的项目时,不会调整其他索引。例如:

NSMutableDictionary *arrayDict = [[NSMutableDictionary alloc] init];
[arrayDict setValue:foo forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:bar forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:fooBar forKey:[NSNumber numberWithInt:[arrayDict count]]];

然后您可以使用 .at 索引访问对象[arrayDict objectForKey:[NSNumber numberWithInt:index]]

请注意,对 setValue:forKey: 的 key 参数使用 NSNumber 会产生警告,但您可以放心地忽略它(或者如果它打扰您,请使用字符串表示)。

于 2012-07-13T06:48:41.923 回答
0

不确定我是否完全理解,但是当你的可变数组中的一个元素被删除时,而不是仅仅删除它,也许将它与另一个“虚拟”占位符对象一起插入?这样,当删除发生时,您的索引根本不会改变

于 2012-07-13T15:46:45.280 回答