You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 3.2自定义洗牌函数无法打乱OfferCard数组问题

Swift 3.2 Custom Shuffle Extension Not Working Reliably

Hey there, let's figure out why your shuffle function isn't behaving as expected! It's frustrating when you’ve tweaked code multiple times and one feature still won’t cooperate—let’s break this down step by step.

You mentioned that sometimes the first element of your array stays the same after shuffling (like "Apple Music" remaining at the top), even though removeFirst() works fine. Let’s start by looking at your custom shuffle implementation and potential issues in Swift 3.2.

Possible Fixes & Improvements

1. Simplify the Shuffle Extension for Int Indexes

Your current shuffle uses the correct Fisher-Yates algorithm, but the generic MutableCollection implementation with IndexDistance type conversions might introduce subtle edge cases. Since you’re working with Array (which uses Int indexes), simplify the extension to avoid ambiguity:

extension MutableCollection where Index == Int {
    mutating func shuffle() {
        guard count > 1 else { return }
        // Fisher-Yates shuffle: iterate from the end to the start
        for i in stride(from: count - 1, through: 1, by: -1) {
            // Generate a random index between 0 and i (inclusive)
            let randomIndex = Int(arc4random_uniform(UInt32(i + 1)))
            swapAt(i, randomIndex)
        }
    }
}

// Add a non-mutating version to return a fresh shuffled array
extension Collection {
    func shuffled() -> [Element] {
        var shuffledArray = Array(self)
        shuffledArray.shuffle()
        return shuffledArray
    }
}

2. Use the Non-Mutating shuffled() Method

Instead of mutating an existing array, use the new shuffled() method to get a clean, shuffled copy. This makes your displayOfferCards() code cleaner and avoids confusion around value-type semantics:

func displayOfferCards() -> Void {
    let offerCards = allOfferCards().shuffled() // Get a new shuffled array
    for (index, offerCard) in offerCards.enumerated() {
        let delay = Double(index) * 0.2
        offerCard.display(delay: delay)
    }
}

3. Verify Shuffle Behavior with Full Array Logs

Sometimes the first element staying the same is just random chance! To confirm if the shuffle is actually working, print the entire array before and after shuffling:

func displayOfferCards() -> Void {
    let originalCards = allOfferCards()
    print("Before shuffle: \(originalCards.map { $0.yourCardTitleProperty })") // Replace with your actual card identifier
    let shuffledCards = originalCards.shuffled()
    print("After shuffle: \(shuffledCards.map { $0.yourCardTitleProperty })")
    
    for (index, offerCard) in shuffledCards.enumerated() {
        let delay = Double(index) * 0.2
        offerCard.display(delay: delay)
    }
}

If only the first element stays the same occasionally but others are rearranged, that’s normal randomness. If the entire array is unchanged every time, double-check that allOfferCards() isn’t returning a static array (your working removeFirst() makes this unlikely, though).

4. Check for Edge Cases

If your array has only 1 or 2 elements, the shuffle won’t change much by design. Ensure numberOfCards from your data source returns a value greater than 1 during testing.

Why Your Original Extension Might Have Issues

Your generic extension is technically correct, but in Swift 3.2, the IndexDistance type conversions (from Int to UInt32 and back) could lead to unexpected behavior in rare cases—especially if you were working with non-Int indexed collections. The simplified version removes that ambiguity while keeping the valid Fisher-Yates logic.


内容的提问来源于stack exchange,提问作者Steven Matthews

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:28:31