Swift: Add prefix (string) into a string - ios

I'm looking for a String function that adds prefix string into an existing string.
The problem I've is: Sometimes, I get a URL string from web service response without keyword http:.
The general form of URL (URL string) should be: http://www.testhost.com/pathToImage/testimage.png
But sometimes I get //www.testhost.com/pathToImage/testimage.png from web service.
Now, I know that I can check, whether prefix http: is there in a string or not, but if there isn't then I need to add prefix into an existing URL string.
Is there any String (or substring or string manipulation) function that adds prefix into my URL string?
I tried into Apple document: String but couldn't find any help.
An alternate way I have is a concatenation of string.
Here is my code:
var imageURLString = "//www.testhost.com/pathToImage/testimage.png"
if !imageURLString.hasPrefix("http:") {
imageURLString = "http:\(imageURLString)" // or "http:"+ imageURLString
}
print(imageURLString)
But is there any standard way or iOS String default function that I can use here?

An alternative is URLComponents. This works with or without http
var urlComponents = URLComponents(string: "//www.testhost.com/pathToImage/testimage.png")!
if urlComponents.scheme == nil { urlComponents.scheme = "http" }
let imageURLString = urlComponents.url!.absoluteString

If "http:" + "example.com" doesn't suit you, you could write your own extension that does this:
extension String {
mutating func add(prefix: String) {
self = prefix + self
}
}
...or make it test the string before adding the prefix, to add it only if it doesn't exist yet:
extension String {
/**
Adds a given prefix to self, if the prefix itself, or another required prefix does not yet exist in self.
Omit `requiredPrefix` to check for the prefix itself.
*/
mutating func addPrefixIfNeeded(_ prefix: String, requiredPrefix: String? = nil) {
guard !self.hasPrefix(requiredPrefix ?? prefix) else { return }
self = prefix + self
}
}
Usage:
// method 1
url.add(prefix: "http:")
// method 2: adds 'http:', if 'http:' is not a prefix
url.addPrefixIfNeeded("http:")
// method 2.2: adds 'http:', if 'http' is not a prefix (note the missing colon which includes to detection of 'https:'
url.addPrefixIfNeeded("http:", requiredPrefix: "http")

There is nothing built in but you could do this in one line with a conditional assignment. See the following:
imageURLString = imageURLString.hasPrefix("http:") ? imageURLString : ("http:" + imageURLString)

I feel that this thread should be retitled to dealing more with URL String Manipulation. To return to prefixing Strings, you don't have to do this using an extension, but to use a Higher Order function (for collections)
Collections of Strings
let prefix = "Mr."
self.dataSource = myMaleFriends.map({ (friend) -> String in
return prefix + " " + friend
})
For prefixing a single word
var name = "Anderson"
name = name.withMutableCharacters({ (name) -> String in
return "Mr. " + name
})

Related

Swift 3 optional string to int

I am using Vapor for Swift backend. Following is the code i am working with.
drop.post("postTodo") { request in
var jsonContent: JSON?
if let contentType = request.headers["Content-Type"], contentType.contains("application/json"), let jsonData = request.json {
jsonContent = jsonData
print("Got JSON: \(jsonContent)")
}
guard let id = jsonContent?.node.object?["id"]?.string
else {
return JSON(["message": "Please include mandatory parameters"])
}
let tempId = Int(id)!
I am getting "id" as optional string for eg: Optional("123") for jsonContent?.node.object?["id"]?.string
When I try to convert it to int using Int(id)! i get back nil
If i try to do let tempId = Int(id!) it gives error.
But when i do the same thing in playground i get proper int value.
let id: String?
id = "1234"
let myInt = Int(id!)
Why Optional string to Int is not working properly in my Vapor app ?
Any idea.
If "id" is an optional string, then you probably don't want to be force unwrapping it with the "!".
The safest approach would be something like:
if let id = id
{
let myIdAsInt = Int(id)
}
The reason it "works" in the playground, is you are definitely assigning a non-nil value to the string (therefore you get away with the force unwrap).
String!might contain a string, or it might contain nil. It’s like a regular optional, but Swift lets you access the value directly without the unwrapping safety. If you try to do it, it means you know there’s a value there – but if you’re wrong your app will crash.
var optionalString: String? = "123"
// first check if it doesn't contain nil
if let str = optionalString {
// string to -> Int
if let id = Int(str) {
print(id) // work with id
}
} else {
// optionalString contains nil
}
what i found is in my iOS code i had a struct with optional properties coz of which when mapped to Dict gave object with optional values to keys.
If I make properties non optional and send it to vapor backend after it works fine.
So basically it was the case of using Optionals properly.

Concatenating an optional and a string

I have a url variable declared like this
var url:String!
url = 'hello'
then I have the base url declared like this:
var baseUrl:String
baseUrl = http://google.com/
Trying to concatenate the 2 values together like
if let tmpurl = url {
println(baseUrl + tmpurl);
}
prints out
http://google.com/Optional('hello')
Why is there the Optional part in the output? I thought the let part would unwrap the optional
The very first thing is that you are using an older version of swift. Please update to 2.1. Secondly this is because you have unwrapped the url variable but its not required. So update your code as:
For swift 2.0
var url:String?
url = 'hello'
var baseUrl:String?
baseUrl = http://google.com/
if let tmpurl = url {
print(baseUrl! + tmpurl);
}

Cyrillic symbols in URL

App crashes with following url:
let jsonUrl = "http://api.com/алматы/events"
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!)
Log:
fatal error: unexpectedly found nil while unwrapping an Optional value
It's because of cyrillic symbols in url. How can I solve this issue. Thanks for your help!
Swift 4
Using String Extension
Create a swift file named String+Extension.swift and paste this code
import UIKit
extension String{
var encodeUrl : String
{
return self.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
}
var decodeUrl : String
{
return self.removingPercentEncoding!
}
}
and Use it like so: (sample according to question):
"http://api.com/алматы/events".encodeUrl
Try this:
let encodedUrl = jsonUrl.stringByAddingPercentEncodingWithAllowedCharacters(URLQueryAllowedCharacterSet)
Something like this:
let apiHost = "http://api.com/"
let apiPath = "алматы/events"
let escapedPath = apiPath.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let url = NSURL(string: "\(apiHost)\(escapedPath!)")
Obviously you should do something smarter than just force unwrap escapedPath.
Using the Wikipedia page for Swift as an example:
https://ru.wikipedia.org/wiki/Swift_(язык_программирования)
Becomes:
https://ru.wikipedia.org/wiki/Swift_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
Which when pasted into the browser takes you to the right page (and most browsers will conveniently render the UFT-8 characters for you).
Non-ASCII characters (and many special characters) need to be escaped in a URL. Chrome and other browser do it automatically. And they unescape the URLs in the address bar for a nicer display.
So if you have a static URL, just paste it into the adressbar, press enter, selected the URL again, copy and paste it to your app:
So instead of:
let jsonUrl = "http://api.com/алматы/events"
You'll get:
let jsonUrl = "http://api.com/%D0%B0%D0%BB%D0%BC%D0%B0%D1%82%D1%8B/events"
Try stringByAddingPercentEncodingWithAllowedCharacters: defined on NSString. You may see people suggesting stringByAddingPercentEscapesUsingEncoding:, but that method is deprecated in iOS 9.
There are also a few predefined NSCharacterSets in Foundation, such as URLHostAllowedCharacterSet and URLPathAllowedCharacterSet. Therefore, if you really have to parse the unescaped URL in code (using preprocessed URLs, mentioned in the accepted answer, is usually a much better idea), you can write a helper method like this:
import Foundation
func url(scheme scheme: String, host: String, path: String) -> NSURL? {
let components = NSURLComponents()
components.scheme = scheme
components.host = host.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
components.path = path.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
return components.URL
}
// evaluates to http://api.com/%25D0%25B0%25D0%25BB%25D0%25BC%25D0%25B0%25D1%2582%25D1%258B/events
url(scheme: "http", host: "api.com", path: "/алматы/events")
Note that the above documentation mentions that
This method is intended to percent-encode an URL component or subcomponent string, NOT an entire URL string.
That's because according RFC 3986, not all parts of an URL can be percent-encoded (e.g. scheme - http/https/etc.)
in xamarin:
var uri = new Uri (url);
var nsurl = new NSUrl (uri.GetComponents (UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
UIApplication.SharedApplication.OpenUrl (nsurl);
URLs cannot contain Cyrillic characters. There are standards how to translate Cyrillic characters into valid URLs - you might find something if you search for "Punicode" (the P is intentional).

Replaced String in Swift 2

So I'm trying to build my app for iOS 9 and am running into one problem. Before, I had a button that would take the string from a label and add it to a string that would take a person to lmgtfy and automatically search for the contents of the string, but now I'm running into an error with map(). Here is the code that worked in iOS 8:
#IBAction func googleButton() {
let replaced = String(map(originalString.generate()) { $0 == " " ? "+" : $0 })
if let url = NSURL(string: "http://google.com/?q=\(replaced)") {
UIApplication.sharedApplication().openURL(url)
}
print(replaced)
}
So now the error I'm getting says, "'map' is unavailable: call the 'map()' method on the sequence." Any ideas? Also, I'm not positive that link will work because it is supposed to be lmgtfy but I couldn't submit this question unless I changed the URL to google.
As of Swift 2, String no longer conforms to SequenceType, therefore you can't call generate on it. Instead you need to use the characters property to obtain a String.CharacterView, which does conform to SequenceType.
Also with Swift 2: map is a method in an extension of SequenceType. Therefore you call it like a method, instead of a free function:
let str = "ab cd ef gh"
let replaced = String(str.characters.map { $0 == " " ? "+" : $0 })
// "ab+cd+ef+gh"
You could also do:
let replaced = str.stringByReplacingOccurrencesOfString(" ", withString: "+")
// "ab+cd+ef+gh"

concatenate enum of strings [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have 2 enums below.
CONFIG_URLS.BASE_URL
CONFIG_URLS.URL1
Each of these enums points to a string.
I want to create a string variable by concatenating BASE_URL and URL1.
Should be swift code.
Can anybody help? Many thanks
I presume that your enum has a raw value of type string. In that case, I would recommend creating a static function that given a enum case returns an absolute URL obtained by appending the value of a case representing a path to the value of the base url:
enum CONFIG_URLS : String {
case BASE_URL = "http://www.myurl.com"
case URL1 = "/some/path"
static func getUrl(url: CONFIG_URLS) -> String {
switch url {
case .BASE_URL:
return BASE_URL.rawValue
default:
return "\(CONFIG_URLS.BASE_URL.rawValue)\(url.rawValue)"
}
}
}
println(CONFIG_URLS.getUrl(.BASE_URL))
println(CONFIG_URLS.getUrl(.URL1))
Alternatively, the static method can be converted to a property, used in a similar way:
enum CONFIG_URLS : String {
case BASE_URL = "http://www.myurl.com"
case URL1 = "/some/path"
var url: String {
switch self {
case .BASE_URL:
return BASE_URL.rawValue
default:
return "\(CONFIG_URLS.BASE_URL.rawValue)\(self.rawValue)"
}
}
}
println(CONFIG_URLS.BASE_URL.url)
println(CONFIG_URLS.URL1.url)
Swift provides the following options.
Option 1
You can concatenate two constant strings as below:
let str1 = "hi" // constant
let str2 = " how are u" // constant
var str3 = string1 + string2 // here str3 is variable which will hold
// the concatenated value i.e. str3 = "hi how are u"
Option 2
You can also append a String value to an existing String variable with the addition assignment operator (+=):
let str1 = "hi"
var str2 = "how are u"
str2 += str1
// str2 now equals "hi how are u"
THe solution was to use rawValue and use + for concatenation (in Swift) , which I wasnt aware about regarding enums.
Thanks everyone.

Resources