How to cast from string to int - ios

I am trying to get the string from " src".."data-lazy-" in variable str, and it's work when i hard code it...
var str = "<h1 style=\"font-family: Helvetica\">Hello Pizza</h1><p>Tap the buttons above to see <strong>some cool stuff</strong> with <code>UIWebView</code><p><img src=\"https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg\" data-lazy-src=\"xxxxxxx\">"
str.rangeOfString(" src")?.startIndex
str.rangeOfString("data-lazy-")?.endIndex
let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 150, length: 245-150))
Result: src=\"https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg\" data-lazy-
Here, i'm trying not to hard code it...
var str = "<h1 style=\"font-family: Helvetica\">Hello Pizza</h1><p>Tap the buttons above to see <strong>some cool stuff</strong> with <code>UIWebView</code><p><img src=\"https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg\" data-lazy-src=\"xxxxxxx\">"
str.rangeOfString(" src")?.startIndex
str.rangeOfString("data-lazy-")?.endIndex
let myNSString = str as NSString
let start = str.startIndex.toInt()
let end = str.endIndex.toInt()
myNSString.substringWithRange(NSRange(location: start, length: end - start))
The code above show error message 'String.index' does not have a member named 'toInt'
My question is how could i solve this problem?
Sorry, i am a fairly new to swift programming language.

Casting is not the problem.
The method substringWithRange() accepts an argument of Range - a Swift range - and a Range can be created with arguments of type String.Index. Thus use:
// I'm ignoring optionals; this code is unsafe and thus only an example
let beg = str.rangeOfString(" src")!
let end = str.rangeOfString("data-lazy-")!
str.substringWithRange(Range(start: beg.endIndex, end: end.startIndex))
Specifically:
15> var str = "abc src=def xyz"
str: String = "abc src=def xyz"
16> var si = str.rangeOfString("src=")!
si: Range<String.Index> = { ... }
17> var ei = str.rangeOfString(" xyz")!
ei: Range<String.Index> = { ... }
18> str.substringWithRange(Range (start: si.endIndex, end: ei.startIndex))
$R3: String = "def"
Don't be confused by the word 'Index' in 'String.Index' - this is not like 'i' in s[i]. A String.Index is an opaque data type; it behaves more like a pointer (in a C-like language). A String.Index has lots to account for in the Unicode world of Swift strings.

Related

Swift String operation not working

I am trying to read the string from a Label and remove the last character form it.
This is how I am trying:
#IBAction func del(sender: UIButton) {
let str = telephone.text!;
let newstr = str.remove(at: str.index(before: str.endIndex))
telephone.text = newstr;
}
When I run, I get an error:
"String" does not have a member named "remove"
Can someone help me figure out the problem?
Just started learning swift :(
remove(at:) mutates the receiver which must therefore be a variable
string:
var str = telephone.text!
str.remove(at: str.index(before: str.endIndex))
telephone.text = str
Alternatively use substring(to:), which returns the new string
instead of modifying the receiver:
let str = telephone.text!
let newstr = str.substring(to: str.index(before: str.endIndex))
telephone.text = newstr
remove is defined as follows:
public mutating func remove(at i: String.Index) -> Character
See the mutating modifier? That means it mutates the instance on which the method is called. In your case, the instance is str, a constant. Since constants cannot be mutated, the code does not compile.
And since remove returns the removed character,
let newstr = str.remove(at: str.index(before: str.endIndex))
here newstr will not be storing the string with the last character removed.
You should rewrite the method like this:
telephone.text!.remove(at: telephone.text!.index(before: telephone.text!.endIndex))
You can use:
let idx = str.index(before: str.endIndex) // compute the index
let s = str.substring(to: idx) // get the substring

How to take NSRange in swift?

I am very much new to swift language. I am performing some business logic which needs to take NSRange from given String.
Here is my requirement,
Given Amount = "144.44"
Need NSRange of only cent part i.e. after "."
Is there any API available for doing this?
You can do a regex-based search to find the range:
let str : NSString = "123.45"
let rng : NSRange = str.range("(?<=[.])\\d*$", options: .RegularExpressionSearch)
Regular expression "(?<=[.])\\d*$" means "zero or more digits following a dot character '.' via look-behind, all the way to the end of the string $."
If you want a substring from a given string you can use componentsSeparatedByString
Example :
var number: String = "144.44";
var numberresult= number.componentsSeparatedByString(".")
then you can get components as :
var num1: String = numberresult [0]
var num2: String = numberresult [1]
hope it help !!
Use rangeOfString and substringFromIndex:
let string = "123.45"
if let index = string.rangeOfString(".") {
let cents = string.substringFromIndex(index.endIndex)
print("\(cents)")
}
Another version that uses Swift Ranges, rather than NSRange
Define the function that returns an optional Range:
func centsRangeFromString(str: String) -> Range<String.Index>? {
let characters = str.characters
guard let dotIndex = characters.indexOf(".") else { return nil }
return Range(dotIndex.successor() ..< characters.endIndex)
}
Which you can test with:
let r = centsRangeFromString(str)
// I don't recommend force unwrapping here, but this is just an example.
let cents = str.substringWithRange(r!)

iOS: Convert UnsafeMutablePointer<Int8> to String in swift?

As the title says, what is the correct way to convert UnsafeMutablePointer to String in swift?
//lets say x = UnsafeMutablePointer<Int8>
var str = x.memory.????
I tried using x.memory.description obviously it is wrong, giving me a wrong string value.
If the pointer points to a NUL-terminated C string of UTF-8 bytes, you can do this:
import Foundation
let x: UnsafeMutablePointer<Int8> = ...
// or UnsafePointer<Int8>
// or UnsafePointer<UInt8>
// or UnsafeMutablePointer<UInt8>
let str = String(cString: x)
Times have changed. In Swift 3+ you would do it like this:
If you want the utf-8 to be validated:
let str: String? = String(validatingUTF8: c_str)
If you want utf-8 errors to be converted to the unicode error symbol: �
let str: String = String(cString: c_str)
Assuming c_str is of type UnsafePointer<UInt8> or UnsafePointer<CChar> which is the same type and what most C functions return.
this:
let str: String? = String(validatingUTF8: c_str)
doesn't appear to work with UnsafeMutablePointer<UInt8>
(which is what appears to be in my data).
This is me trivially figuring out how to do something like the C/Perl system function:
let task = Process()
task.launchPath = "/bin/ls"
task.arguments = ["-lh"]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
var unsafePointer = UnsafeMutablePointer<Int8>.allocate(capacity: data.count)
data.copyBytes(to: unsafePointer, count: data.count)
let output : String = String(cString: unsafePointer)
print(output)
//let output : String? = String(validatingUTF8: unsafePointer)
//print(output!)
if I switch to validatingUTF8 (with optional) instead of cString, I get this error:
./ls.swift:19:37: error: cannot convert value of type 'UnsafeMutablePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')
let output : String? = String(validatingUTF8: unsafePointer)
^~~~~~~~~~~~~
Thoughts on how to validateUTF8 on the output of the pipe (so I don't get the unicode error symbol anywhere)?
(yes, I'm not doing proper checking of my optional for the print(), that's not the problem I'm currently solving ;-) ).

Using character delimiters to find and highlight text in Swift

I previously developed an android app that served as a reference guide to users. It used a sqlite database to store the information. The database stores UTF-8 text without formatting (i.e. bold or underlined)
To highlight what sections of text required formatting I enclosed them using delimiter tokens specifically $$ as this does not appear in the database as information. Before displaying the text to the user I wrote a method to find these delimiters and add formatting to the text contained within them and delete the delimiters. so $$foo$$ became foo.
My java code for this is as follows:
private static CharSequence boldUnderlineText(CharSequence text, String token) {
int tokenLen = token.length();
int start = text.toString().indexOf(token) + tokenLen;
int end = text.toString().indexOf(token, start);
while (start > -1 && end > -1)
{
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
//add the formatting required
spannableStringBuilder.setSpan(new UnderlineSpan(), start, end, 0);
spannableStringBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, 0);
// Delete the tokens before and after the span
spannableStringBuilder.delete(end, end + tokenLen);
spannableStringBuilder.delete(start - tokenLen, start);
text = spannableStringBuilder;
start = text.toString().indexOf(token, end - tokenLen - tokenLen) + tokenLen;
end = text.toString().indexOf(token, start);
}
return text;
}
I have recreated my app in Swift for iOS and it is complete apart from showing the correct formatting. It appears that Swift treats strings differently from other languages.
So far I have tried using both NSString and String types for my original unformatted paragraph and get manage to get the range, start and end index of the first delimiter:
func applyFormatting2(noFormatString: NSString, delimiter: String){
let paragraphLength: Int = noFormatString.length //length of paragraph
let tokenLength: Int = delimiter.characters.count //length of token
let rangeOfToken = noFormatString.rangeOfString(formatToken) //range of the first delimiter
let startOfToken = rangeOfToken.toRange()?.startIndex //start index of first delimiter
let endOfToken = rangeOfToken.toRange()?.endIndex //end index of first delimiter
var startOfFormatting = endOfToken //where to start the edit (end index of first delimiter)
}
OR
func applyFormatting(noFormatString: String, token: String){
let paragraphLength: Int = noFormatString.characters.count
let tokenLength: Int = token.characters.count //length of the $$ Token (2)
let rangeOfToken = noFormatString.rangeOfString(formatToken) //The range of the first instance of $$ in the no format string
let startOfToken = rangeOfToken?.startIndex //the starting index of the found range for the found instance of $$
let endOfToken = rangeOfToken?.endIndex //the starting index of the found range for the found instance of $$
var startOfFormatting = endOfToken
}
I appreciate this code is verbose and has pointless variables but it helps me think though my code when I'm working out a problem.
I am currently struggling to workout how to find the second/closing delimiter. I want to search through the string from a specific index as I did in Java using the line
int end = text.toString().indexOf(token, start);
however I cannot work out how to do this using ranges.
Can anyone help me out with either how to correctly identify where the closing delimiter is or how to complete the code block to format all the required text?
Thanks
Aldo
How about using NSRegularExpression?
public extension NSMutableAttributedString {
func addAttributes(attrs: [String : AnyObject], delimiter: String) throws {
let escaped = NSRegularExpression.escapedPatternForString(delimiter)
let regex = try NSRegularExpression(pattern:"\(escaped)(.*?)\(escaped)", options: [])
var offset = 0
regex.enumerateMatchesInString(string, options: [], range: NSRange(location: 0, length: string.characters.count)) { (result, flags, stop) -> Void in
guard let result = result else {
return
}
let range = NSRange(location: result.range.location + offset, length: result.range.length)
self.addAttributes(attrs, range: range)
let replacement = regex.replacementStringForResult(result, inString: self.string, offset: offset, template: "$1")
self.replaceCharactersInRange(range, withString: replacement)
offset -= (2 * delimiter.characters.count)
}
}
}
Here is how you call it.
let string = NSMutableAttributedString(string:"Here is some $$bold$$ text that should be $$emphasized$$")
let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(15)]
try! string.addAttributes(attributes, delimiter: "$$")
The iOS way of doing this is with NS[Mutable]AttributedStrings. You set dictionaries of attributes on text ranges. These attributes include font weights, sizes, colors, line spacing, etc.

Append String in Swift

I am new to iOS. I am currently studying iOS using Objective-C and Swift.
To append a string in Objective-C I am using following code:
NSString *string1 = #"This is";
NSString *string2 = #"Swift Language";
NSString *appendString=[NSString stringWithFormat:#"%# %#",string1,string2];
NSLog(#"APPEND STRING:%#",appendString);
Anyone please guide me.
Its very simple:
For ObjC:
NSString *string1 = #"This is";
NSString *string2 = #"Swift Language";
ForSwift:
let string1 = "This is"
let string2 = "Swift Language"
For ObjC AppendString:
NSString *appendString=[NSString stringWithFormat:#"%# %#",string1,string2];
For Swift AppendString:
var appendString1 = "\(string1) \(string2)"
var appendString2 = string1+string2
Result:
print("APPEND STRING 1:\(appendString1)")
print("APPEND STRING 2:\(appendString2)")
Complete Code In Swift:
let string1 = "This is"
let string2 = "Swift Language"
var appendString = "\(string1) \(string2)"
var appendString1 = string1+string2
print("APPEND STRING1:\(appendString1)")
print("APPEND STRING2:\(appendString2)")
In Swift, appending strings is as easy as:
let stringA = "this is a string"
let stringB = "this is also a string"
let stringC = stringA + stringB
Or you can use string interpolation.
let stringC = "\(stringA) \(stringB)"
Notice there will now be whitespace between them.
Note: I see the other answers are using var a lot. The strings aren't changing and therefore should be declared using let. I know this is a small exercise, but it's good to get into the habit of best practices. Especially because that's a big feature of Swift.
let string2 = " there"
var instruction = "look over"
choice 1 :
instruction += string2;
println(instruction)
choice 2:
var Str = instruction + string2;
println(Str)
ref this
Add this extension somewhere:
extension String {
mutating func addString(str: String) {
self = self + str
}
}
Then you can call it like:
var str1 = "hi"
var str2 = " my name is"
str1.addString(str2)
println(str1) //hi my name is
A lot of good Swift extensions like this are in my repo here, check them out: https://github.com/goktugyil/EZSwiftExtensions
You can simply append string
like:
var worldArg = "world is good"
worldArg += " to live";
var string1 = "This is ";
var string2 = "Swift Language";
var appendString = string1 + string2;
println("APPEND STRING: \(appendString)");
According to Swift 4 Documentation,
String values can be added together (or concatenated) with the addition operator (+) to create a new String value:
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"
You can also append a String value to an existing String variable with the addition assignment operator (+=):
var instruction = "look over"
instruction += string2
// instruction now equals "look over there"
You can append a Character value to a String variable with the String type’s append() method:
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"
> Swift2.x:
String("hello ").stringByAppendingString("world") // hello world
Strings concatenate in Swift language.
let string1 = "one"
let string2 = "two"
var concate = " (string1) (string2)"
playgroud output is "one two"
In the accepted answer PREMKUMAR there are a couple of errors in his Complete code in Swift answer. First print should read (appendString) and Second print should read (appendString1). Also, updated println deprecated in Swift 2.0
His
let string1 = "This is"
let string2 = "Swift Language"
var appendString = "\(string1) \(string2)"
var appendString1 = string1+string2
println("APPEND STRING1:\(appendString1)")
println("APPEND STRING2:\(appendString2)")
Corrected
let string1 = "This is"
let string2 = "Swift Language"
var appendString = "\(string1) \(string2)"
var appendString1 = string1+string2
print("APPEND STRING:\(appendString)")
print("APPEND STRING1:\(appendString1)")
SWIFT 2.x
let extendedURLString = urlString.stringByAppendingString("&requireslogin=true")
SWIFT 3.0
From Documentation:
"You can append a Character value to a String variable with the String type’s append() method:" so we cannot use append for Strings.
urlString += "&requireslogin=true"
"+" Operator works in both versions
let extendedURLString = urlString+"&requireslogin=true"
let firstname = "paresh"
let lastname = "hirpara"
let itsme = "\(firstname) \(lastname)"

Resources