admin管理员组

文章数量:1290950

I am working on an iOS app using UIKit and Core Data that involves graph-based navigation where nodes represent different moves in a martial arts system. Users can navigate through these nodes in different modes, including Specific Sparring Mode, which introduces randomness in node selection.

Everything works fine until a Fail Node appears. At that point:

A normal node starts incorrectly redirecting to a Fail Node’s Primary instead of its intended connections. This issue persists until the user refreshes the page. Fail Nodes themselves never redirect incorrectly, meaning only normal nodes get corrupted.

Expected Behavior -

Only Secondary Nodes should redirect to their corresponding Primary Nodes. Fail Nodes should not interfere with the navigation logic of Normal Nodes.

Debugging navigateToPrimaryNode(for:) I added print() statements to track which nodes were being redirected. Found that after encountering a Fail Node, a normal node unexpectedly started redirecting to a Fail Node’s Primary. Checking startSpecificSparring(for:) I logged the nodes that were being hidden or shown. Verified that Fail Nodes were being displayed correctly, but some normal nodes were disappearing or redirecting incorrectly. Investigating updateLinePosition(for:) and redrawLines() I checked whether incorrect lines were being drawn between nodes after encountering a Fail Node. Found that the visual representation of the nodes seemed fine, meaning the issue wasn't purely a UI bug. Resetting & Retrying Specific Sparring Mode I used retrySpecificSparring() to see if the issue resolved itself on a retry. The issue persisted even after retrying, meaning something was being modified persistently. Verifying restoreTextFields() Restarted the app to see if Core Data was saving incorrect relationships. Confirmed that the issue disappears after refreshing, meaning it’s likely not a Core Data storage issue, but something happening dynamically during navigation. What I Expected

Secondary nodes should only redirect to their respective Primary nodes. Fail Nodes should not interfere with normal nodes. After a failure, normal nodes should continue functioning as expected. Retrying Specific Sparring should reset node behavior properly.

Findings - Normal nodes sometimes get "stuck" redirecting to a Fail Node’s Primary. The issue only happens after encountering a Fail Node. Refreshing the app fixes the issue, meaning it's not being saved incorrectly in Core Data. The problem persists across retries but disappears on full page refresh. If you can also advise me on how to better ask my question that would be helpful so I can modify to be better understandable. This is all of my relative code pieces.

func navigateToPrimaryNode(for node: DragableNode) -> DragableNode {
    
    if node.type == .primary {
        return node
    }

    //  If node is secondary, find its correct primary node
    if node.type == .secondary, let primaryNode = findPrimaryNode(for: node) {
       
        return primaryNode
    }

    
    if node.entity.nodeType == .fail, let primaryFailNode = findPrimaryNode(for: node) {
       
        return primaryFailNode
    }

   
    if node.entity.nodeType != .fail {
        if let cachedPrimary = findPrimaryNode(for: node) {
          
            return cachedPrimary
        }
    }

    return node
}

Piece 2

func findPrimaryNode(for node: DragableNode) -\> DragableNode? {
    guard node.type == .secondary else { return nil }

    let primaryCandidates = textFields.filter {
        $0.type == .primary && $0.text == node.text
    }

    if primaryCandidates.isEmpty {
      
        return nil
    }

    if primaryCandidates.count == 1 {
        
        return primaryCandidates.first
    }

  
    for primary in primaryCandidates {
        if primary.entity.children?.contains(node.entity) == true {
          
            return primary
        }
    }
    return primaryCandidates.first
}

piece 3

func findPrimaryTextField(named name: String) -\> DragableNode? {
    return textFields.first { $0.text == name && $0.type == .primary }
}

piece 4

@objc func handleNodeTap(\_ sender: UITapGestureRecognizer) {
    guard let tappedNode = sender.view as? DragableNode else { return }

   
        if tappedNode.type == .secondary, let primaryNode = findPrimaryNode(for: tappedNode) {
            
            enterViewMode(for: primaryNode)
            return
        }
    
    
    
    if isInViewMode {
          enterViewMode(for: tappedNode)
          return
      }

    if isInSpecificSparring {
          
           startSpecificSparring(for: tappedNode, difficulty: currentSparringDifficulty)

         
           DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
               let visibleNodes = self.contentView.subviewspactMap { $0 as? DragableNode }.filter { !$0.isHidden }
               self.recenterAndZoomToFit(nodes: visibleNodes)
           }
           return
       }

  
    UIView.animate(withDuration: 0.3, animations: {
        tappedNode.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
        tappedNode.alpha = 1.0
    }, completion: { _ in
        // Reset the scaling back to normal
        UIView.animate(withDuration: 0.2) {
            tappedNode.transform = CGAffineTransform.identity
        }

        
        self.enterViewMode(for: tappedNode)
    })
}

piece 5

@objc private func retrySpecificSparring() {
    guard let firstNode = firstViewModeNode else {
   

        if let lastUsedNode = textFields.first(where: { !$0.isHidden }) {
            firstViewModeNode = lastUsedNode
            startSpecificSparring(for: lastUsedNode, difficulty: currentSparringDifficulty)
        }
        return
    }

   

    
    DispatchQueue.main.async {
        for subview in self.contentView.subviews {
            if let textNode = subview as? DragableNode {
                textNode.isHidden = true
                textNode.alpha = 0.0
            }
        }

       
        self.contentView.layer.sublayers?.removeAll(where: { $0 is CAShapeLayer })

       
        self.startSpecificSparring(for: firstNode, difficulty: self.currentSparringDifficulty)
    }
}

piece 6

func startSpecificSparring(for node: DragableNode, difficulty: Int) {
    guard let superview = self.contentView else { return }

    var targetNode: DragableNode = navigateToPrimaryNode(for: node)

   
    print("

本文标签: iosSpecific Sparring Mode Causes Incorrect Node RedirectionStack Overflow