How to add a character at a particular index in string in Swift
If you are declaring it as NSMutableString
then it is possible and you can do it this way:
let str: NSMutableString = "3022513240)"
str.insert("(", at: 0)
print(str)
The output is :
(3022513240)
EDIT:
If you want to add at starting:
var str = "3022513240)"
str.insert("(", at: str.startIndex)
If you want to add character at last index:
str.insert("(", at: str.endIndex)
And if you want to add at specific index:
str.insert("(", at: str.index(str.startIndex, offsetBy: 2))
How to insert character into string in Swift 2.0?
This appears to have already been solved in this answer.
Swift 2.0
You can use a string extension:
extension String {
func insert(string:String,ind:Int) -> String {
return String(self.characters.prefix(ind)) + string + String(self.characters.suffix(self.characters.count-ind))
}
}
used like:
var url = "http://www.website.com"
url = url.insert("s", ind: 4) // outputs https://www.website.com
Insert character after first N characters in Swift
You just need to anchor your regex pattern to the start of the string:
let regex = #"^(.{\#(every)})"#
Swift 3 string insert
label.insert("9", ind:2)
For index, you need to provide the index, not integer.
// to insert at 0 position
let str = label.text!;
label.text!.insert("9", at:str.startIndex);
or
// to insert at 2nd position
label.text!.insert("9", at: str.index(str.startIndex, offsetBy: 2)) ;
Get nth character of a string in Swift
Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4 and Swift 5.
Swift 4 or later
The Substring
type was introduced in Swift 4 to make substrings
faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return.
Try it out here
extension StringProtocol {
subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
subscript(range: Range<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: ClosedRange<Int>) -> SubSequence {
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
return self[startIndex..<index(startIndex, offsetBy: range.count)]
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}
To convert the Substring
into a String
, you can simply
do String(string[0..2])
, but you should only do that if
you plan to keep the substring around. Otherwise, it's more
efficient to keep it a Substring
.
It would be great if someone could figure out a good way to merge Note: This answer has been already edited, it is properly implemented and now works for substrings as well. Just make sure to use a valid range to avoid crashing when subscripting your StringProtocol type. For subscripting with a range that won't crash with out of range values you can use this implementation
these two extensions into one. I tried extending StringProtocol
without success, because the index
method does not exist there.
Why is this not built-in?
The error message says "see the documentation comment for discussion". Apple provides the following explanation in the file UnavailableStringAPIs.swift:
Subscripting strings with integers is not available.
The concept of "the
i
th character in a string" has
different interpretations in different libraries and system
components. The correct interpretation should be selected
according to the use case and the APIs involved, soString
cannot be subscripted with an integer.Swift provides several different ways to access the character
data stored inside strings.
String.utf8
is a collection of UTF-8 code units in the
string. Use this API when converting the string to UTF-8.
Most POSIX APIs process strings in terms of UTF-8 code units.
String.utf16
is a collection of UTF-16 code units in
string. Most Cocoa and Cocoa touch APIs process strings in
terms of UTF-16 code units. For example, instances of
NSRange
used withNSAttributedString
and
NSRegularExpression
store substring offsets and lengths in
terms of UTF-16 code units.
String.unicodeScalars
is a collection of Unicode scalars.
Use this API when you are performing low-level manipulation
of character data.
String.characters
is a collection of extended grapheme
clusters, which are an approximation of user-perceived
characters.
Note that when processing strings that contain human-readable text,
character-by-character processing should be avoided to the largest extent
possible. Use high-level locale-sensitive Unicode algorithms instead, for example,
String.localizedStandardCompare()
,
String.localizedLowercaseString
,
String.localizedStandardRangeOfString()
etc.
insert string in string at index (swift)
In my solution I use a regex finding everything between <
and >
to find the whole HTML tag. After the tag is found I use the replacingOccurrences(of:with:)
method to
- replace the closing tag’s bracket with the additional
style=
attribute (plus a closing bracket) to create the modified tag, - replace the original tag with the modified tag.
Here’s the code:
let string = "Lorem lipsum <a href=\"www.example.com\"> lorem lipsum <a href=\"www.somewhereelse.com\"> dolor sit amet."
let insertString = " style=\"text-decoration: none\">"
var modifiedString = string
let regex = try! NSRegularExpression(pattern: "<.*?>")
let range = NSRange(string.startIndex..., in: string)
let matches = regex.matches(in: string, range: range)
let tags = matches.map { String(string[Range($0.range, in: string)!]) }
for tag in tags {
let newTag = tag.replacingOccurrences(of: ">", with: insertString)
modifiedString = modifiedString.replacingOccurrences(of: tag, with: newTag)
}
print(modifiedString)
The updated code now uses a loop to replace all tags with the enhanced tags as per your requirement. For this to work you will have to change the regex to non-greedy: <.*?>
instead of <.*>
.
How does String.Index work in Swift
All of the following examples use
var str = "Hello, playground"
startIndex
and endIndex
startIndex
is the index of the first characterendIndex
is the index after the last character.
Example
// character
str[str.startIndex] // H
str[str.endIndex] // error: after last character
// range
let range = str.startIndex..<str.endIndex
str[range] // "Hello, playground"
With Swift 4's one-sided ranges, the range can be simplified to one of the following forms.
let range = str.startIndex...
let range = ..<str.endIndex
I will use the full form in the follow examples for the sake of clarity, but for the sake of readability, you will probably want to use the one-sided ranges in your code.
after
As in: index(after: String.Index)
after
refers to the index of the character directly after the given index.
Examples
// character
let index = str.index(after: str.startIndex)
str[index] // "e"
// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range] // "ello, playground"
before
As in: index(before: String.Index)
before
refers to the index of the character directly before the given index.
Examples
// character
let index = str.index(before: str.endIndex)
str[index] // d
// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range] // Hello, playgroun
offsetBy
As in: index(String.Index, offsetBy: String.IndexDistance)
- The
offsetBy
value can be positive or negative and starts from the given index. Although it is of the typeString.IndexDistance
, you can give it anInt
.
Examples
// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index] // p
// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range] // play
limitedBy
As in: index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
- The
limitedBy
is useful for making sure that the offset does not cause the index to go out of bounds. It is a bounding index. Since it is possible for the offset to exceed the limit, this method returns an Optional. It returnsnil
if the index is out of bounds.
Example
// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
str[index] // p
}
If the offset had been 77
instead of 7
, then the if
statement would have been skipped.
Why is String.Index needed?
It would be much easier to use an Int
index for Strings. The reason that you have to create a new String.Index
for every String is that Characters in Swift are not all the same length under the hood. A single Swift Character might be composed of one, two, or even more Unicode code points. Thus each unique String must calculate the indexes of its Characters.
It is possible to hide this complexity behind an Int index extension, but I am reluctant to do so. It is good to be reminded of what is actually happening.
Related Topics
Where Is the Official Documentation for Cvopenglestexture Method Types
How to Animate Uitableviewcell Height Using Auto-Layout
Is It Safe to Delete SQLite's Wal File
Importing Swift Framework into a Objective-C Project
Attach a PDF File to Email - Swift
Share Image with Hashtag via Uiactivityviewcontroller (Twitter, Facebook, Instagram)
Observing Change in Frame of a Uiview During Animation
Cannot Convert Value of Type Nsattributedstring.Documentattributekey to .Documentreadingoptionkey
How to Install the "App Store" in an iOS Simulator
How to Resize Uitableviewcell to Fit Its Content
Xcode 4.3:Missing Icons for iOS Apps in Organizer's Archives
Disable Autolayout Localization Behavior (Rtl - Right to Left Behavior )
A Server with the Specified Hostname Could Not Be Found
"This App Is Not Allowed to Query for Scheme Cydia" iOS9 Error