UIView带来SubviewToFront:确实*不*将视图带到前面

我正在实施一个简单的iOS纸牌游戏,允许用户以通常的方式拖动卡片。 这些卡用UIView子类CardView 。 所有卡片视图都是兄弟姐妹,它们是SolitaireView子视图。 以下代码片段尝试“将卡片放在前面”,以便在拖动时它位于所有其他视图上方:

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if (touch.view.tag == CARD_TAG) { CardView *cardView = (CardView*) touch.view; ... [self bringSubviewToFront:cardView]; ... } } 

不幸的是,卡的z顺序在拖动期间保持不变。 在下面的图片中,我拖着国王。 请注意它在左图像中的九个顶部是正确的,但在右图像中的两个(实际上在整个堆栈下)不正确:

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

我也试过改变layer.zPosition属性也无济于事。 如何在拖动过程中将卡片视图置于正面? 我很神秘。

证实。 bringSubviewToFront:导致调用layoutSubview 。 由于我的layoutSubviews版本在所有视图上设置了z顺序,因此撤消了我在上面的touchesBegan:withEvent代码中设置的z顺序。 Apple应该在bringSubviewToFront文档中提到这种副作用。

我创建了一个名为CardLayerCALayer子类,而不是使用UIView子类。 我在下面列出的KlondikeView子类中处理触摸。 topZPosition是一个实例var,用于跟踪所有卡的最高zPosition。 请注意,修改zPosition通常是动画的 – 我在下面的代码中将其关闭:

 -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { UITouch *touch = [touches anyObject]; CGPoint touchPoint = [touch locationInView:self]; CGPoint hitTestPoint = [self.layer convertPoint:touchPoint toLayer:self.layer.superlayer]; CALayer *layer = [self.layer hitTest:hitTestPoint]; if (layer == nil) return; if ([layer.name isEqual:@"card"]) { CardLayer *cardLayer = (CardLayer*) layer; Card *card = cardLayer.card; if ([self.solitaire isCardFaceUp:card]) { //... [CATransaction begin]; // disable animation of z change [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; cardLayer.zPosition = topZPosition++; // bring to highest z // ... if card fan, bring whole fan to top [CATransaction commit]; //... } // ... } }