将数据从一个视图控制器直接传递到第三个视图控制器

时间:2019-07-17 07:57:14

标签: ios swift xcode

是否有任何方法可以将数据从第一视图控制器传递到(例如)第三视图控制器,而无需通过第二视图控制器传递数据? 我实际上在第4个视图控制器上有一个最终的提交按钮,该按钮直接从第一个视图控制器收集所有数据。 我希望每个视图控制器的数据都直接传输到提交按钮所在的第4个视图控制器,而无需通过视图控制器到达那里。

我已经尝试过通过视图控制器传递数据,认为可以有一种更直接的方式直接传输数据,尤其是图像,因为这些是我数据的主要部分。

2 个答案:

答案 0 :(得分:0)

为此,您可以将“模型”与委托模式一起使用。 模型是可以被多个VC访问的类(或结构)。 该委托将用于“通知”属性值已更改。

/// Should be implemented by your VC
protocol MyModelDelegate: AnyObject {
    func dataToShareChanged(to data: dataToShare)
}

/// Use the same instance for the VC1 and VC4
final class MyModel {
    weak var delegate: MyModelDelegate?
    var dataToShare: Foo {
        didSet { delegate?.dataToShareChanged(to: dataToShare) }
    }
}

在您的情况下,分别排在第一和第四位。每个VC都应具有相同的模型实例。如果初始化VC,则可以将模型对象交给VC,从而达到这一目的。 如果使用情节提要板,则必须在“ viewDidLoad”中设置模型。

所以您的VC看起来像:

class MyController: UIViewController, MyModelDelegate {
     var model: MyModel?

     func viewDidLoad() {
     ...
         model.delegate = self
     }

     // Implementation of the delegate function.
     func dataToShareChanged(to data: dataToShare) {
          /// assign the new data value here
     }
}

如果使用此方法,则完全不需要通过VC传递数据。只需在模型中分配新值,另一个VC将通过模型委托函数接收这些数据更改。

答案 1 :(得分:0)

将数据从一个视图控制器传递到下一个视图控制器不一定是一件坏事。但是,当处理大量数据(尤其是图像)时,通过这种方法很容易遇到内存压力。

如果您所需要做的只是向当前的viewcontroller邻居(向前或向后)通知有关数据更改的代理方式,则很有希望。

让我提出另一套解决方案。

首先,不要管理内存中的图像对象。如果您不需要其他任何内容,请将其写入应用程序的临时目录中,保留URL并放开UIImage对象。下面的代码段使您可以使用名称将UIImage对象保存到NSTemporaryDirectory并返回URL对象。

func saveImageToTempDirectory(image: UIImage, withName: String) -> URL? {
    let url = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
        .appendingPathComponent(withName, isDirectory: false)
        .appendingPathExtension("jpg")

    // Then write to disk
    if let data = image.jpegData(compressionQuality: 0.8) {
         do {
            try data.write(to: url)
            return url
        } catch {
            //handle error
            return nil
        }
    }
    return nil
}

您可以选择将该方法中的URL从一个视图控制器传递到另一个。在Util类中使用此方法可以更好地进行组织。

方法1

将来自特定ViewController的图像URL写入本地存储。您可以使用UserDefaults作为最简单的方法。您还可以在保存临时目录的同时为每个ViewController创建单独的文件夹。

方法2

单子。单身人士一向不满意,因为它们始终保持状态,并且变得难以测试和/或调试,但您可以利用一个Singleton类,该类将所有本地URL作为数组的一部分保存。

final class ImagePathManager {
    static let shared = ImagePathManager()

    var firstViewControllerImages: [URL] = []

    //Initializer access level change now
    private init(){}
}

您可以将第一个viewcontroller的URL附加到ImagePathManager.shared.firstViewControllerImages,并以相同的方式从应用程序中的任何其他位置访问它们。

话虽如此,但Singleton模式的使用是一个滑坡,在应用程序中使用它时应始终非常小心。