我正在以编程方式构建基于选项卡栏 Controller 的应用程序。我试图弄清楚如何将数据从我认为是一个选项卡栏 View Controller (viewControllers [1] 顶部的附加 VC)的子项发送到另一个选项卡的 Collection View 在 viewControllers[0] 处禁止 VC)。我在这里阅读了很多条目,但似乎没有一个对我有用,或者我不理解它们。
基本上,在 viewControllers[1] 的 VC 中,我通过在主 TabVC 中实现此代码实现了一个自定义的全屏摄像头。
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if viewControllers?.firstIndex(of: viewController) == 1 {
present(cameraVC, animated: true, completion: nil)
}
return true
}
然后在该 VC 中,我正在捕获图像并使用 present(editVC) 将新的 editVC 堆叠在该图像之上以显示捕获的照片以及一些编辑工具。我说“堆叠”,尽管我不知道这些在这样呈现时是否真的成为层次结构的一部分?可以澄清一下。从那个 editingVC,我正在执行编辑并将文件保存到 documentsDirectory。一切正常,图像成功保存。但是我遇到困难的地方是获取我已保存的照片的路径地址返回到 viewControllers[0] 的 Collection View VC,以便我可以用照片填充它的单元格。
我已经尝试创建一个委托(delegate),但我意识到我无法将 viewControllers[0] 设置为 viewControllers[1] 的(第一个或第二个?)子代的委托(delegate)。 (我不清楚上面的代码是否本质上使 cameraVC 成为 viewControllers[1] 本身的子项。)或者我可以/是否推荐它?
然后我尝试创建一个状态类,其中包含一个 URL 数组(用于保存文件的路径),editVC 可以写入,viewControllers[0] Collection View 可以读取。但我似乎无法让 editVC 更新该数组。我怀疑我无意中创建了该“状态”的多个实例。来 self 不同的 VC 的类(class)?
我有太多代码,我不确定要发布什么,但希望这是相关的:
在状态类中:
class StatePaths {
var urls = [URL]()
}
在editVC中
// declaration at the beginning of the class
var statePaths: StatePaths?
// In the save func:
let imageName = UUID().uuidString
let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)
if let jpegData = image.jpegData(compressionQuality: 0.8) {
try? jpegData.write(to: imagePath)
self.statePaths.urls.append(imagePath)
self.dismiss(animated: true)
}
在viewControllers[0]的 Collection View 中
var statePaths = StatePaths()
// In the cellForItem func:
let path = statePaths[indexPath.item]
if let image = UIImage(contentsOfFile: path.path) {
cell.imageView.image = image
}
我还实现了一些显示图像正在保存的打印语句,但它们没有填充 statePaths 类。我还在我的收藏 VC 的 ViewWillAppear 上实现了 collectionView.reloadData()。
我们将不胜感激任何有关这些方法或任何其他方法的帮助。
最佳答案
I suspect I am inadvertently creating multiple instances of that "state". class from each of my different VCs?
是的,“statePaths”是多个实例,不需要使用它。您需要在 viewControllers[0] 中获取保存的图像。
此外,更清晰的方法是将此代码与单独的模型或服务分离。 例如:
struct ImageStorage {
static var documentsDirectory: String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
}
static var imagesDirectory: String {
let imagesDirectory = documentsDirectory + "/images/"
if !FileManager.default.fileExists(atPath: imagesDirectory) {
try? FileManager.default.createDirectory(atPath: imagesDirectory, withIntermediateDirectories: true, attributes: nil)
}
return imagesDirectory
}
static var images: [UIImage] {
guard let paths = try? FileManager.default.contentsOfDirectory(atPath: imagesDirectory) else {
return []
}
let images = paths.compactMap { UIImage(contentsOfFile: imagesDirectory + $0) }
return images
}
static func save(_ image: UIImage) {
let imageName = UUID().uuidString
let imagePath = imagesDirectory + imageName
let imageUrl = URL(fileURLWithPath: imagePath)
guard let jpegData = image.jpegData(compressionQuality: 0.8) else {
return
}
try? jpegData.write(to: imageUrl)
}
}
然后在viewController中使用它:
ImageStorage.save(image)
ImageStorage.images
更新。质疑传递数据:视情况而定。
在某些情况下,您可以使用委托(delegate)、tabBarViewController 堆栈、NotificationCenter 等将数据传递给 viewController。
但在其他情况下更容易使用单例来临时存储数据。 正如我所看到的,viewControllers 之间的联系在您的案例中并不那么明显。所以单例是首选。
例如:
class StatePaths {
static let shared = StatePaths()
private init() {}
var urls = [URL]()
}
StatePaths.shared.urls = urls
let urls = StatePaths.shared.urls
关于ios - 将数据从一个 Tab Bar View Controller 的子项(我认为?)传递到另一个 TabBarVC 的 Collection View? (以编程方式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57701718/