swiftui - 应用程序终止时未保存图像列表的 SwiftUI 拖放重新排序
问题描述
我正在尝试为水平列表中显示的自定义图像实现拖放功能。问题是当我用拖放重新排序图像时,我想将它保存到应用程序的文档目录中,并在应用程序再次打开时获取它。我被卡住了,不知道如何实现它,如果你知道如何实现它,请帮助,谢谢,非常感谢
这是代码:
struct CustomImage: Identifiable, Equatable, Hashable {
var id: Int
var image: UIImage
}
struct ContentView: View {
@State private var selected = -1
@ObservedObject var viewModel: ViewModel = ViewModel()
var body: some View {
ZStack {
Color.gray.opacity(0.2)
.ignoresSafeArea()
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 4) {
ForEach(viewModel.images) { image in
Image(uiImage: image.image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 150)
.overlay(
Rectangle()
.stroke(selected == image.id ? Color.white : .clear, lineWidth: 5)
.animation(.spring())
)
.padding(5)
.onTapGesture {
selected = image.id
}
.onDrag({
// Setting Current Page
selected = 0
return NSItemProvider(object: image.image)
})
.onDrop(of: [.image], delegate: DropViewDelegate(page: CustomImage(id: image.id, image: image.image), viewModel: viewModel))
}
}
.padding(.leading, 8)
}
}
}
}
struct DropViewDelegate: DropDelegate {
var page: CustomImage
var viewModel: ViewModel
func performDrop(info: DropInfo) -> Bool {
viewModel.currentPage = nil
return true
}
// When User Dragged Into New Page
func dropEntered(info: DropInfo) {
if viewModel.currentPage == nil {
viewModel.currentPage = page
}
// Getting From and To Index
// From Index
let fromIndex = viewModel.images.firstIndex { (page) -> Bool in
return page.id == viewModel.currentPage?.id
} ?? 0
// To Index
let toIndex = viewModel.images.firstIndex { (page) -> Bool in
return page.id == self.page.id
} ?? 0
// Safe check if both are not same
if fromIndex != toIndex {
// Animation
withAnimation(.default) {
// Swapping Data
let fromPage = viewModel.images[fromIndex]
viewModel.images[fromIndex] = viewModel.images[toIndex]
viewModel.images[toIndex] = fromPage
viewModel.renameImage(from: "\(fromIndex)", to: "\(toIndex)")
}
}
// print("From Index - \(fromIndex)")
// print("To Index - \(toIndex)")
}
// Setting Action as Move
func dropUpdated(info: DropInfo) -> DropProposal? {
return DropProposal(operation: .move)
}
}
class ViewModel: ObservableObject {
@State var images: [CustomImage] = [
CustomImage(id: 1, image: UIImage(systemName: "command")!),
CustomImage(id: 2, image: UIImage(systemName: "option")!),
CustomImage(id: 3, image: UIImage(systemName: "delete.right")!),
CustomImage(id: 4, image: UIImage(systemName: "shift")!),
CustomImage(id: 5, image: UIImage(systemName: "globe")!),
]
@Published var currentPage: CustomImage?
func getSavedImage(url: URL) -> UIImage? {
UIImage(contentsOfFile: url.path)
}
func loadImageFromDocumentDirectory(nameOfImage: String, storyName: String) -> UIImage? {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
guard let dirPath = paths.first else { return nil }
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("ProjectImages/\(nameOfImage)")
print("Image URL --- \(imageURL)")
guard let image = UIImage(contentsOfFile: imageURL.path) else { return nil }
return image
}
func renameImage(from: String, to: String) {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
guard let dirPath = paths.first else { return }
let originPath = URL(fileURLWithPath: dirPath).appendingPathComponent("ProjectImages/\(from)")
let destitationPath = URL(fileURLWithPath: dirPath).appendingPathComponent("ProjectImages/\(to)")
do {
try FileManager.default.moveItem(at: originPath, to: destitationPath)
try FileManager.default.moveItem(at: destitationPath, to: originPath)
} catch {
print("Reordering in storage error - \(error)")
}
}
func numberOfImages(in name: String) -> Int {
var number = 0
let fileManager = FileManager.default
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageURLDir = URL(fileURLWithPath: dirPath).appendingPathComponent("ProjectImages/\(name)")
do {
let fileURLs = try fileManager.contentsOfDirectory(at: imageURLDir, includingPropertiesForKeys: nil)
number = fileURLs.count
} catch {
print(error.localizedDescription)
return 0
}
}
return number
}
@discardableResult
func loadRegularImagesFromAlbum() -> [UIImage] {
var images: [UIImage] = []
let fileManager = FileManager.default
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageURLDir = URL(fileURLWithPath: dirPath).appendingPathComponent("ProjectImages")
do {
let fileURLs = try fileManager.contentsOfDirectory(at: imageURLDir, includingPropertiesForKeys: nil)
for imageURL in fileURLs {
if let image = getSavedImage(url: imageURL), !fileManager.fileExists(atPath: imageURL.absoluteString) {
images.append(image)
}
}
} catch {
print(error.localizedDescription)
}
}
return images
}
func getDirectoryPath() -> NSURL {
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("ProjectImages")
let url = NSURL(string: path)
return url!
}
func saveImageDocumentDirectory(image: UIImage, imageName: String) {
let fileManager = FileManager.default
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("ProjectImages")
if !fileManager.fileExists(atPath: path) {
try! fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
}
let url = NSURL(string: path)
let imagePath = url!.appendingPathComponent(imageName)
let urlString: String = imagePath!.absoluteString
let imageData = image.jpegData(compressionQuality: 0.5)
//let imageData = UIImagePNGRepresentation(image)
fileManager.createFile(atPath: urlString as String, contents: imageData, attributes: nil)
print("Image is saved lo file")
print("Image name is \(imageName)")
print("Path is - \(path)")
}
}
解决方案
推荐阅读
- python - 如何调整 iotools.read_tmy3 函数的 tmy_data 输出中的索引。如果其他人有同样的问题,我如何解决我的问题
- tensorflow - TensorFlow Lite 量化未能改善推理延迟
- php - 如何打印在codeigniter的其他表中多次使用的主键名称
- pytorch - 在 pytorch 中保存模型时,某些参数未保存
- gembox-spreadsheet - PDF转换问题
- multithreading - 偶然的多线程,但不是单线程,Bug (Common Lisp)
- javascript - 如何使用 args 作为 json 字段
- scala - Spark 按列值对数据集进行分区
- reactjs - 选择数据表中的行(mui-datatable)
- postgresql - Sequelize 模型关联 - 缺少外键