How can I move file in Document Picker in SwiftUI - swiftui

I am getting "File don't exists" error in Move Content function. I have shared the console outputs below. How can I move a file in the document picker into a file of my own application?
When the user selects a file from Document Picker, I want to move the selected file to the SafeFile folder in the Folder application on the iPhone. I couldn't do this.
Move Content:
func moveContentMyApp(atPath: String, toPath: String, myFile: MyFile) {
let emptyFile = MyFile(fileName: "", fileExtension: "", textForFile: "", image: nil, typeOfFile: "", isLock: false, folderIcon: .empty, fileCreateDate: "", fileSize: 0, localPath: "")
guard let originURL = takeMainDirectoryURL(addPath: atPath, myFile: emptyFile) else {
return
}
guard let destinationURL = takeMainDirectoryURL(addPath: toPath, myFile: myFile) else {
return
}
print("origin2: \(originURL)")
print("destination2: \(destinationURL)")
if manager.fileExists(atPath: originURL.path) {
do {
try manager.moveItem(atPath: originURL.path, toPath: destinationURL.path)
} catch let error {
print("Error Description: \(error.localizedDescription)")
}
} else {
print("File don't exists")
}
}
Move Function:
func moveContentOnMyApp() {
print("origin path: \(originPath)")
print("destinationPath: \(destinationPath)")
myAppFileManager.moveContentMyApp(atPath: originPath, toPath: destinationPath, myFile: selectedFile)
originPath = ""
destinationPath = ""
takeArrayOfItems()
}
File Importer:
.fileImporter(isPresented: $isOpenDocumentPicker, allowedContentTypes: [.image, .jpeg, .png, .gif, .pdf], onCompletion: { (res) in
do {
let fileURL = try res.get()
if fileURL.startAccessingSecurityScopedResource() {
safeFileVM.setOriginPath(currentPath: fileURL.path)
safeFileVM.selectedFile.fileName = "asikarti"
safeFileVM.selectedFile.fileExtension = "pdf"
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
safeFileVM.setDestinationPath(currentPath: currentLocation)
safeFileVM.moveContentOnMyApp()
}
} else {
print("olmuyor")
}
fileURL.stopAccessingSecurityScopedResource()
} catch {
print("error")
}
})
Console:
origin path: /private/var/mobile/Containers/Shared/AppGroup/5C8D117E-13BB-46C3-80DB-27F700A54680/File Provider Storage/HES/asikarti.pdf
destinationPath: /test
origin2: file:///var/mobile/Containers/Data/Application/34FD7C1C-3478-41B8-B7F0-AC2D32C5DAC0/Documents//private/var/mobile/Containers/Shared/AppGroup/5C8D117E-13BB-46C3-80DB-27F700A54680/File%20Provider%20Storage/HES/asikarti.pdf
destination2: file:///var/mobile/Containers/Data/Application/34FD7C1C-3478-41B8-B7F0-AC2D32C5DAC0/Documents//test/asikarti.pdf
File don't exists

Related

Conditional use in view for SwiftUI

I have a model with data string of name and a bool of UE. I'm trying to display item.name whenever UE is true. My issue is when whenever I run the code the data doesn't seem to read the UE. I got an error displaying the item.UE as a text view. The data that I am getting it from is from a database the item.name works without the conditional.
struct AttendingUsersView: View {
#ObservedObject var model = UserViewModel()
var body: some View {
VStack {
List (model.list) { item in
if item.UE == true {
Text(item.name)
} else {
Text("This isnt working")
}
}
DismissButton
}
}
I've tried displaying the item.UE to see what it would display but I get an error saying "No exact matches in call to initializer".
UserViewModel file
class UserViewModel: ObservableObject {
#Published var list = [Username]()
func addData(name: String, UE: Bool) {
//get a reference to the database
let db = Firestore.firestore()
// Add a new document in collection "username"
db.collection("usernames").document(UserDefaults.standard.object(forKey: "value") as! String).setData([
// MARK: Change the parameters to the users inputed choices
"name": name,
"UE": UE
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
func getData() {
//get a reference to the database
let db = Firestore.firestore()
//Read the documents at a specific path
db.collection("usernames").getDocuments { snapshot, error in
//checking for errors
if error == nil {
//no errors
if let snapshot = snapshot {
// update
DispatchQueue.main.async {
// Get all the documents and create usernames
self.list = snapshot.documents.map { d in
//Create a Username
return Username(id: d.documentID, name: d["name"] as? String ?? "", UE: (d["UE"] != nil)) //cast as a string and if not found return as a empty string
}
}
}
} else {
//Handle the error
}
}
}
}
Username model
struct Username: Identifiable {
var id: String
var name: String
var ue: Bool
}
Try this, with fixes for your ue in your getData, and
in the view display.
struct ContentView: View {
var body: some View {
AttendingUsersView()
}
}
struct AttendingUsersView: View {
#StateObject var model = UserViewModel() // <-- here
var body: some View {
VStack {
List (model.list) { item in
if item.ue { // <-- here
Text(item.name)
} else {
Text("This is working ue is false")
}
}
// DismissButton
}
}
}
class UserViewModel: ObservableObject {
// for testing
#Published var list:[Username] = [Username(id: "1", name: "item-1", ue: false),
Username(id: "2", name: "item-2", ue: true),
Username(id: "3", name: "item-3", ue: false)]
func addData(name: String, UE: Bool) {
//get a reference to the database
let db = Firestore.firestore()
// Add a new document in collection "username"
db.collection("usernames").document(UserDefaults.standard.object(forKey: "value") as! String).setData([
// MARK: Change the parameters to the users inputed choices
"name": name,
"UE": UE
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
func getData() {
//get a reference to the database
let db = Firestore.firestore()
//Read the documents at a specific path
db.collection("usernames").getDocuments { snapshot, error in
//checking for errors
if error == nil {
//no errors
if let snapshot = snapshot {
// update
DispatchQueue.main.async {
// Get all the documents and create usernames
self.list = snapshot.documents.map { d in
//Create a Username
// -- here, ue:
return Username(id: d.documentID, name: d["name"] as? String ?? "", ue: (d["UE"] != nil)) // <-- here ue:
}
}
}
} else {
//Handle the error
}
}
}
}
struct Username: Identifiable {
var id: String
var name: String
var ue: Bool
}

CoreData adding entity

Here is how I add new entity.
func addCountry(name: String, code: String, flagImageUri: String?, wikiDataId: String) {
let newCountry = CountryEntity(context: container.viewContext)
newCountry.name = name
newCountry.code = code
newCountry.flagImageUri = flagImageUri
newCountry.wikiDataId = wikiDataId
save()
}
Here is my data:
However when I use the add function in my view, I got this error:
CoreData: error: +[CountryEntity entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
And this is my button:
Button(action: {
country.isFaved = !country.isFaved
coreDataModel.addCountry(name: country.name, code: country.code, flagImageUri: country.flagImageUri, wikiDataId: country.wikiDataId)
}) {
Image(systemName: "star.fill")
.foregroundColor(country.isFaved ? .black : .white)
.scaledToFit()
}
This is the whole class. I'm fetching, saving ,adding and deleting all data here. I did everything like the video I watched in youtube.
class DataController: ObservableObject {
let container = NSPersistentContainer(name: "CountryCoreData")
#Published var savedCountries: [CountryEntity] = []
init() {
container.loadPersistentStores(completionHandler: { _, error in
if let error = error {
print("CoreData failed to load: \(error.localizedDescription)")
} else {
print("Successfully loaded")
}
})
}
func fetchCountries() -> [CountryEntity]? {
let request = NSFetchRequest<CountryEntity>(entityName: "CountryEntity")
do {
let fetchedCountries = try container.viewContext.fetch(request)
return fetchedCountries
} catch {
print("Something went wrong while data fetching \(error)")
return nil
}
}
func delete(code: String) {
guard let fetchedCountries = fetchCountries() else { return }
for country in fetchedCountries {
if country.code!.contains(code) {
container.viewContext.delete(country)
save()
}
}
}
func addCountry(name: String, code: String, flagImageUri: String?, wikiDataId: String) {
let newCountry = CountryEntity(context: container.viewContext)
print("OSMAN")
newCountry.name = name
newCountry.code = code
newCountry.flagImageUri = flagImageUri
newCountry.wikiDataId = wikiDataId
save()
}
func save() {
do {
try container.viewContext.save()
fetchCountries()
} catch {
print("Error while saving the data: \(error)")
}
}
}
How can I solve this problem?

How get image filename from PHAsset of library in swift3

I'm using QBImagePicker. I tried to get image file name, but it's very difficult. What can I do for that? I don't know it.
func qb_imagePickerController(_ imagePickerController: QBImagePickerController!, didFinishPickingAssets assets: [Any]!) {
let requestOptions = PHImageRequestOptions()
requestOptions.resizeMode = PHImageRequestOptionsResizeMode.exact
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat
// this one is key
requestOptions.isSynchronous = true
for asset in assets {
if ((asset as AnyObject).mediaType == PHAssetMediaType.image) {
PHImageManager.default().requestImage(for: asset as! PHAsset, targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: {
(pickedImage, info) in
self.selectImage.image = self.resizeImage(getImageView: self.selectImage, originImage: pickedImage!)
})
}
}
imagePickerController.dismiss(animated: true, completion: nil)
}
Try this
if let fileName = Asset.value(forKey: "filename") as? String{
print(fileName)
}
let originalName = PHAssetResource.assetResources(for: asset).first?.originalFilename
print("original File name \(originalName)")

How to save the video to separate folder with app name in ios swift3?

I'm facing the issue while saving the video to the directory.
I'm using following code:-
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print("Error creating directory: \(error.localizedDescription)")
}
let filePath="\(dataPath.absoluteString)video.mp4";
DispatchQueue.main.async(execute: {
urlData?.write(toFile: filePath, atomically: true);
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: NSURL(fileURLWithPath: filePath) as URL)
}) { completed, error in
if completed {
print("Video is saved!")
// self.videoAlertMeaage(isError: false)
}else{
// self.videoAlertMeaage(isError: true)
}
}
})

Writing to text file in swift 3

I am trying to write data that is inputted by a user via UITextField to a text file. I am successfully able to do this by the code I have written below. However, when I tried to save more data it will replace the existing data in the textfile with the new data that is being saved. for example, if I save the string 'hello world' and then save another string saying 'bye'. I will only see the string 'bye' in the textfile. Is there a way I can modify my code so I can see 'hello world' on one line of the textile and 'bye' on another.
#IBAction func btnclicked(_ sender: Any) {
self.savedata(value: answer.text!)
}
func savedata (value: String){
let fileName = "Test"
let DocumentDirURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("txt")
print("FilePath: \(fileURL.path)")
let writeString = NSString(string: answer.text!)
do {
// Write to the file
try writeString.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8.rawValue)
} catch let error as NSError {
print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
}
}
Here is an example using FIleHandler, adapted to Swift 3, from here (of course you should add all the error handling code that's missing in my example) :
let dir = FileManager.default.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first!
let fileurl = dir.appendingPathComponent("log.txt")
let string = "\(NSDate())\n"
let data = string.data(using: .utf8, allowLossyConversion: false)!
if FileManager.default.fileExists(atPath: fileurl.path) {
if let fileHandle = try? FileHandle(forUpdating: fileurl) {
fileHandle.seekToEndOfFile()
fileHandle.write(data)
fileHandle.closeFile()
}
} else {
try! data.write(to: fileurl, options: Data.WritingOptions.atomic)
}
do {
let fileHandle = try FileHandle(forWritingTo:pathWithFileName)
fileHandle.seekToEndOfFile()
let oldData = try String(contentsOf: pathWithFileName,encoding: .utf8).data(using: .utf8)!
var data = periodValue.data(using: .utf8)!
fileHandle.write(data)
fileHandle.closeFile()
} catch {
print("Error writing to file \(error)")
}
Here is a Swift 4 version as an extension to String.
extension String {
func writeToFile(fileName: String) {
guard let dir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return
}
let fileUrl = dir.appendingPathComponent(fileName)
guard let data = self.data(using: .utf8) else {
return
}
guard FileManager.default.fileExists(atPath: fileUrl.path) else {
try? data.write(to: fileUrl, options: .atomic)
return
}
if let fileHandle = try? FileHandle(forUpdating: fileUrl) {
fileHandle.seekToEndOfFile()
fileHandle.write(data)
fileHandle.closeFile()
}
}
}