Insert a character in the filename - swift

I want to insert a suffix in the name of a file (.jpg) I loaded. Say the original filename is "AAA.jpg" and the user specified a suffix like "changed", I want to save in the same folder a new file named "AAA changed.jpg". Here is what I tried:
var noExt = chosenFiles[indexInChoseFiles].deletingPathExtension() // full_path/filename (but PercentEncoding)
let aString=noExt.absoluteString + " " + filenameSuffix + ".jpg" // insert the suffix and the extension
var bString=aString.removingPercentEncoding! // get rid of PercentEncoding
var newPath=URL(string: bString) // *** nil ***
newPath=URL(string: aString) // *** nil ***
aString and bString are OK, but newPath returns nil in both cases.

You almost never should use .absoluteString for the manipulation
of URLs, and removing the percent encoding makes it an invalid
URL string, so that the conversion back to URL fails.
Here is a simplified demonstration of the problem:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
let path = url.absoluteString // "file:///path/to/my%20documents/aaa.jpg"
let path2 = path.removingPercentEncoding! // "file:///path/to/my documents/aaa.jpg"
let url2 = URL(string: path2) // nil
One possible solution is to use .path instead:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
print(url)
// "file:///path/to/my%20documents/aaa.jpg"
let path = url.deletingPathExtension().path
let newPath = path + " CHANGED" + ".jpg"
let newURL = URL(fileURLWithPath: newPath)
print(newURL)
// file:///path/to/my%20documents/aaa%20CHANGED.jpg
Another solution, using only URL methods:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
print(url)
// "file:///path/to/my%20documents/aaa.jpg"
let ext = url.pathExtension // "jpg"
let basename = url.deletingPathExtension().lastPathComponent // "aaa"
let newUrl = url.deletingLastPathComponent()
.appendingPathComponent(basename + " CHANGED")
.appendingPathExtension(ext)
print(newUrl)
// "file:///path/to/my%20documents/aaa%20CHANGED.jpg"

Related

Loading many javascript files with interdependencies into a JavaScriptCore context

The following Q&A illustrates how to load a single javascript file into JavaScriptCore: https://stackoverflow.com/a/26979233/1056563
func analyzeText(scriptName: String) {
var ext = scriptName.pathExtension
var fileName = scriptName.substringToIndex(
advance(scriptName.startIndex,
scriptName.utf16Count - ext.utf16Count - 1))
if fileExtension.utf16Count == 0 {
fileName = scriptName
ext = "js"
}
let url = NSBundle.mainBundle()
.URLForResource(fileName, withExtension: ext)
let scriptCode = String(contentsOfURL: url!,
encoding: NSUTF8StringEncoding,
error: nil)!
var context = JSContext(virtualMachine: JSVirtualMachine())
context.evaluateScript(scriptCode)
/* ... */
}
What if there are many javascript files and they have interdependencies: can they be loaded sequentially in reverse order of their dependencies and expect to resolve properly?
utils.js
file1NeedingUtils.js
file2NeedingFile1.js
So then :
func analyzeText(jsContext: JSContext, scriptName: String) {
var ext = scriptName.pathExtension
var fileName = scriptName.substringToIndex(
advance(scriptName.startIndex,
scriptName.utf16Count - ext.utf16Count - 1))
if fileExtension.utf16Count == 0 {
fileName = scriptName
ext = "js"
}
let url = NSBundle.mainBundle()
.URLForResource(fileName, withExtension: ext)
let scriptCode = String(contentsOfURL: url!,
encoding: NSUTF8StringEncoding,
error: nil)!
jsContext.evaluateScript(scriptCode)
}
var jsCtx = JSContext(virtualMachine: JSVirtualMachine())
["utils.js","file1NeedingUtils.js","file2NeedingFile1.js"]
.forEach( x in analyzeScript(jsCtx, x))
Notice that we are sharing the same JSContext across all the invocations.
That functionality is typically the domain of the browser to handle. I am planning to go that route but am wondering if there were likely to be issues . In addition are there optimizations to the process that would be helpful?

URL Object is nil after creating it with let constant string url

Why does the first example give me a nil and the second example give me a valid URL object. I am trying to use this jsonUrlString constant and it's not working.
1)
let jsonUrlString = """
https://myURI.domain.com/
"""
let temp = URL(string: jsonUrlString)
2)
let temp = URL(string: "https://myURI.domain.com/")
The first example has lots of extra spaces in the URL so it's not valid.
It's the same as:
let temp = URL(string: " https://myURI.domain.com/")
It would work if you had:
let jsonUrlString = """
https://myURI.domain.com/
"""
This defines the string without the extra spaces.

NSArrayURL , userDefault filePath and URL

I have one pdf source code and I want to add the Url in Array and use UserDefault
let defaults = UserDefaults.standard
struct Constants {
static let myKeyURL = "myKeyUrl"
}
I download the Pdf Like This
let documentsPath =NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
After I save the Path like This
var arrayUrl = [String]()
arrayUrl.append(filePath)
self.defaults.set(arrayUrl, forKey: Constants.myKeyURL)
Now I want to Read
var arrayUrl = [String]()
defaults.stringArray(forKey: Constants.myKeyURL)
arrayUrl = defaults.stringArray(forKey: Constants.myKeyURL)!
I need to Read in This Model
documents = arrayUrl.flatMap { PDFDocument(url: $0 ) }
But I received
Cannot convert value of type 'String' to expected argument type 'URL'
I need this URL (arrayUrl) File in this format file:///private/var/mobile/Containers/Data/Application/----/Documents/Sample.pdf
The error is clear:
PDFDocument(url: expects URL, you pass String which is a classic type mismatch.
You have to create URL instances from the strings
documents = arrayUrl.flatMap { PDFDocument(url: URL(fileURLWithPath: $0) ) }
However you are discouraged from saving the full path because the path to the Documents folder changes. Save only the file name or relative path and get the actual path to the Documents folder on each application launch.

Reading URLS in JSON api with swift

For work we have a third party company which supply a JSON api for some functionality. The JSON contains urls which I try to map in my code with URL(string: ...) but this fails on some urls which have spaces.
For example:
var str = "https://google.com/article/test test.html"
let url = URL(string: str) //nil
Should I ask the third party to encode their URLs ?
Is this normal or should I try to add encoding myself?
Encoding myself is hard I think because the path should be encoded different from the query and the host shouldn't be encoded etc.
Or am I overthinking this?
If the URL contains spaces in its path, escape the characters with addingPercentEncoding(withAllowedCharacters passing the urlPathAllowed character set:
let str = "https://google.com/article/test test.html"
if let escapedString = str.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlPathAllowed),
let url = URL(string:escapedString) {
print(url)
} else {
print("url \(str) could not be encoded")
}
What I would do if I were you, is to split the string up on the space, try converting each of the elements to a url, and when that works save it in your variable.
var str = "https://google.com/article/test test.html"
var url: URL? = nil
for urlString in str.components(separatedBy: .whitespacesAndNewlines) {
let url = URL(string: urlString)
if url != nil {
break
}
}
// url might be nil here, so test for value before using it
If each URL that you get from the API is in the format in your example, you can instead just grab the first element after spitting the string.
var str = "https://google.com/article/test test.html"
if let urlString = str.components(separatedBy: .whitespacesAndNewlines).first {
let url = URL(string: urlString)
}
// url might be nil here, so test for value before using it

Url issue in swift 3.0 using Alamofire

I am trying to send sms and my url with numbers is "http://api.appname.my/sendSms.php?message=hello&phone=687985<6123488<60149041982" but it get shorten to this "http://api.appname.my/sendSms.php?message=hello&phone=687985" so why it is removing other numbers.Here is my code
number = number + "60149041982"
let url = "http://api.appname.my/sendSms.php?message=hello&phone=\(number)"
Alamofire.request(url).response{ (responseObject) -> Void in
print(responseObject)
}
I think your should encode the < character to %3C
let urlString = "http://api.appname.my/sendSms.php?message=hello&phone=\(number)"
let url = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print("Result: " + url!)
// Result: http://api.appname.my/sendSms.php?message=hello&phone=687985%3C6123488%3C60149041982