【问题标题】:Check which ViewController made a segue (from the destination ViewController)检查哪个 ViewController 进行了 segue(来自目标 ViewController)
【发布时间】:2016-06-25 15:59:02
【问题描述】:

我有一个代码,可以为我的 12 个 ViewController 提供随机序列。

在 ViewController1 中是这样的;

let segues = ["1-2", "1-3", "1-4", "1-5", "1-6", "1-7", "1-8", "1-9", "1-10", "1-11", "1-12"]
        let index = Int(arc4random_uniform(UInt32(segues.count)))
        let segueName = segues[index]
        self.performSegueWithIdentifier(segueName, sender: self)

在 ViewController 2 中它看起来一样,但 segue 名称更改为;

let segues = ["2-1", "2-3", "2-4", "2-5", "2-6", "2-7", "2-8", "2-9", "2-10", "2-11", "2-12"]

"1" 变为 "2")- 以此类推,适用于所有 12 个 ViewController。

.

现在,我要做的是删除已经显示的 ViewController,这样下一个 segue 就不会回到之前的任何 ViewController。

例子:

• ViewController1 对 ViewController2 进行 segue ("1-2")

• ViewController2 从数组segues 中删除segue "2-1"

• ViewController2 然后对 ViewController3 "1-3" 进行 segue

• ViewController3 删除segue "3-1""3-2"

等等……

【问题讨论】:

  • 所以您只想从 segues-array 中随机挑选出一个 segue-identifier,但在全部显示之前没有任何重复?
  • @T.BenjaminLarsen 没错! :-)

标签: ios arrays swift uiviewcontroller segue


【解决方案1】:

这是一种方法:

  1. 将您访问过的视图控制器数组作为属性保存在每个视图控制器中。我们称之为visited。此外,创建一个名为TracksVisited协议,您的所有视图控制器都将采用该协议:

    protocol TracksVisited {
        var visited: [Int] { get set }
    }
    
    class ViewController1: UIViewController, TracksVisited {
        var visited = [Int]()
    
        ...
    }
    
    class ViewController2: UIViewController, TracksVisited {
        var visited = [Int]()
    
        ...
    }
    
  2. 将当前的 viewController 编号添加到此列表中:

    let vc = 3  // current viewController
    visited.append(vc)
    
  3. 生成segues的列表并选择一个:

    // generate list of all viewControllers
    let all = Array(1...12)
    
    // remove visited from all
    let rest = all.filter { !visited.contains($0) }
    
    // create list of segues
    let segues = rest.map { "\(vc)-\($0)" }
    
    // choose random segue and go there
    let index = Int(arc4random_uniform(UInt32(segues.count)))
    let segueName = segues[index]
    self.performSegueWithIdentifier(segueName, sender: self)
    
  4. prepareForSegue中,将visited的列表传递给目标viewController:

    if let destinationViewController = segue.destinationViewController as? TracksVisited {
        destinationViewController.visited = visited
    }
    

【讨论】:

  • 没有destinationViewController 吗?如果它们是随机选择的,我怎么知道哪个是目的地? :-)
  • 我更新了如何将访问的数组发送到每个 viewController 的答案。
  • 顺便说一句,你怎么能在不使用我的 segues 的名字和我不改变它们的情况下做到这一点?我可以删除我之前做的所有转场吗?这太疯狂了?! :)
  • 您可以从原始代码中删除let segues = ["1-2", "1-3", "1-4", "1-5", "1-6", "1-7", "1-8", "1-9", "1-10", "1-11", "1-12"],但不要删除您在情节提要中连接的实际转场!
  • 好的,谢谢!只要我摆脱情节提要中的转场,我就可以删除 ViewController10 吗?我必须更改代码吗?
【解决方案2】:

我强烈怀疑您的主逻辑可以变得更易于管理,但是在当前设置下,我建议使用单独的 SegueCoordinator 来提供下一个 segue 直到它用完 (2-11, 11 -3, 3-6, 6-4...) 等:

import GameplayKit

class SegueCoordinator {
    private var numberOfViewControllers = 0
    private var segues = [String]()

    init(numberOfViewControllers: Int) {
        self.numberOfViewControllers = numberOfViewControllers
        setupSegues()
    }

    func nextSegue() -> String? {
        let segue = segues.first
        segues.removeFirst()
        return segue
    }

    private func setupSegues() {
        let allIds = Array(1...numberOfViewControllers)
        var shuffleIds = GKRandomSource().arrayByShufflingObjectsInArray(allIds) as! [Int]
        while shuffleIds.count > 1 {
            let availableIds = shuffleIds.filter{$0 != shuffleIds.first!}
            let segue = "\(shuffleIds.first!)-\(availableIds.first!)"
            segues.append(segue)
            shuffleIds.removeFirst()
        }
    }
} 

然后,您将从要启动的任何 ViewController 创建协调器:let coordinator = SegueCoordinator(numberOfViewControllers: 12)(这可以很容易地更改为从协调器本身随机选择一个 firstControler)。

然后只需要向协调器询问下一个Segue:

let segue = coordinator.nextSegue()

将协调器传递给 prepareForSegue 中的 nextVC。

【讨论】:

  • 如何使用这段代码?我是否将let segues 数组与我的字符串一起保存?我如何以及何时使用您的let segue = coordinator.nextSegue()
  • 不,你不再需要字符串数组了。每个 viewController 都需要有一个 segueCoordinator 属性,并在 prepareForSegue destinationViewController.segueCoordinator = segueCoordinator 中传递它,当需要移动到新的 viewController 时,您只需请求 nextSegue 并将字符串用作 segueIdentifier。 performSegueWithIdentifier(segue, sender: self)
  • 当它是随机的并且我不知道它是哪一个时,我如何将它传递给“destinationViewController”? :-)
猜你喜欢
  • 2020-09-03
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-07
相关资源
最近更新 更多