NSMutableArray难度

时间:2012-06-26 03:56:02

标签: iphone ios xcode nsmutablearray icarousel

如果你想看到代码我有问题,这里是链接: Code

我的问题与我的past question有关。

我的NSMutableArray确实存在问题,我目前正在使用iCarousel作为我的slotMachine对象(slot1和slot2)。我的应用程序以这种方式工作:

PhotoViewController我创建了包含缩略图图像的视图,然后使用按钮指定其框架。因此,如果按下1个图像,它将通过NSUserDefaults保存该整数。 然后我会在carouselViewController

中检索它

我想调整阵列,但我不能。 我也在这里试过我的问题: Comparing with NSMutableArray 如果我能像Array 2那样做,那将会很容易,但仍然无效。

附加信息:)

我这样做了,有一个ViewController包含UIImageView,里面有一个按钮,所以当用户点击它时,我的CustomPicker会弹出。我的CustomPicker包含用户在相机胶卷上拾取的图像。因此,每个按钮都有一个使用iCarouselView发送到NSUserDefaults的特定值。第一个插槽的carousel1和第二个插槽的carousel2。

这就是我想做的事情:我想强行让它停在用户选择的索引上。 (我在我的carouselDidEndScrollingAnimtaion中做了什么)

在我的carouselDidEndScrollingAnimation方法中,我测试了我的所有条件(单独),它在比较方面完美地运作。 然后当我结合条件时,前两个比较或STOP是正确的,但接下来的两个总是错误的。或者有时混淆了。

我需要滚动两个特定的索引/整数,即User Picked(我已经完成了)能够滚动2对它们但接下来的两个总是错误的,因为我认为索引正在调整。

PICTURES:

图片以下是我的PhotoViewController,其中包含我的游戏的比较阶段SETTINGUIImageVIewUIButton。图片将根据它放入数字中是有力的,应该有力地展示。

enter image description here

当我的iCarousel启动时,它会停止,例如在下图中(与上面的图片不同): enter image description here

将强行滚动到PhotoViewController

中输入的图像

分为: enter image description here

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

你必须做4次(对)---->在这里显示我通过按钮.95通过NSUserDefaults得到他们的索引然后发送到iCarouselView

然后当你完成时(按下Done按钮),它将转到iCarouselView然后,如上图所示那是它的视图。 按下它会旋转几秒钟,然后完成但不会停留在PhotoView中挑选的用户时,它会强行滚动到该索引。

问题:

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

希望你理解我的问题。

5 个答案:

答案 0 :(得分:1)

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

我不是百分之百确定发生了什么。用户做什么(以及在什么视图中)以及之后触发的内容(呈现哪个视图)。

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

根据上面的图片,图片以单个索引关闭。这是每次都这样吗?也许从阵列中取出会有问题。

如果你给我一些我可以提供帮助的信息。

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

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

在所有其他代码块上,您可以调用每个旋转木马。在上面的代码中,您可以两次调用轮播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。

这是对的吗?

答案 1 :(得分:1)

  

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

您必须修改iCarousel管理其索引的方式的唯一方法是修改代码。实际上,如果你查看iCarousel.m中的removeViewAtIndex方法,你会看到索引是通过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. 当轮播停止时,如果在所需项目上没有偶然,则“强制”它滚动到该项目。

  3. 删除一些元素之后没有理由不应该这样做(除非iCarousel有一些错误,然后解决方案就是捕获bug)。唯一的部分是知道您希望转移到哪个索引。

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

    这对我来说听起来不太正确。因此,当为carousel1调用carouselDidEndScrollingAnimation时,你应该找到一种只滚动carousel1的方法,而当为carousel2调用carouselDidEndScrollingAnimation时,你应该只滚动carousel2。

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

    的想法
    1. 让旋转木马停止;

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

    3. 似乎不是最佳实现,因为用户会看到旋转木马停止然后重新开始。

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

      具体来说,请查看iCarousel.m中的step方法。在每个帧处调用此方法以生成轮播动画。现在,在这种方法中有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));
              }
          }
      }
      

      并且您看到当旋转木马停止减速时,它会再次滚动。这与您正在进行的完全相同,因此您可能会找到一种方法来修改此代码,并使轮播完全滚动到您需要的索引。通过这种方式,您可以更加平滑地旋转旋转木马。

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

答案 2 :(得分:1)

参考你的问题。您希望从阵列中删除成员时,不会更改其成员索引的数组。

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

答案 3 :(得分: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]]];

然后您可以使用[arrayDict objectForKey:[NSNumber numberWithInt:index]]来访问索引处的对象。

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

答案 4 :(得分:0)

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