Displaying text one character at a time in swift 2.0
I suppose Swiftworthy is subjective, but here's another implementation based on how your code currently works that wraps the NSTimer in a Swift class.
class Timer {
typealias TimerFunction = (Int)->Bool
private var handler: TimerFunction
private var i = 0
init(interval: NSTimeInterval, handler: TimerFunction) {
self.handler = handler
NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: "timerFired:", userInfo: nil, repeats: true)
}
@objc
private func timerFired(timer:NSTimer) {
if !handler(i++) {
timer.invalidate()
}
}
}
class ViewController: UIViewController {
let text: NSAttributedString = {
let font = UIFont(name: "Georgia", size: 18.0) ?? UIFont.systemFontOfSize(18.0)
return NSAttributedString(string: "A long time ago, in a galaxy far, far away ...", attributes: [NSFontAttributeName: font])
}()
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView(frame: CGRect(x: 100, y: 120, width: CGRectGetWidth(self.view.frame), height: CGRectGetWidth(self.view.frame)-20))
self.view.addSubview(textView)
let _ = Timer(interval: 0.1) {i -> Bool in
textView.attributedText = self.text.attributedSubstringFromRange(NSRange(location: 0, length: i+1))
return i + 1 < self.text.string.characters.count
}
}
}
Insert Charc into String in a Range where character X exist at Index - swift 2.0
The following finds the first space in the range 15..<END_OF_YOUR_STRING
, and replaces it with a new line (\n
). In your question you stated you explicitly wanted to look for a space in range 15...20
, and also insert a new line after the space. Below I have assumed that you actually want:
- To replace the space by a new line, since you'll otherwise have a trailing space on the line following the line break.
- To search for the first space starting at index
15
, but continuing until you find one (otherwise: if you find no space within range15...20
, no line break should be inserted?).
Both of these deviations from your question can be quite easily reverted, so tell me if you'd prefer me to follow your instructions to specifically to the point (rather than including my own reason), and I'll update this answer.
Solution as follows:
var foo = "This is my somewhat long test string"
let bar = 15 /* find first space " " starting from index 'bar' */
if let replaceAtIndex = foo[foo.startIndex.advancedBy(bar)..<foo.endIndex]
.rangeOfString(" ")?.startIndex.advancedBy(bar) {
foo = foo.stringByReplacingCharactersInRange(
replaceAtIndex...replaceAtIndex, withString: "\n")
}
print(foo)
/* This is my somewhat
long test string */
Note that there is a off-by-one difference between finding a space in the range of 15 to 20 and the 15:th to 20:th character (the latter is in the range 14...19
). Above, we search for the first space starting at the 16th character (index 15
).
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.
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 allow only certain set of numbers in a UITextfield in swift 2.0
Set keyboard type as Number Pad
add this
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
if let text = textField.text {
let newStr = (text as NSString)
.stringByReplacingCharactersInRange(range, withString: string)
if newStr.isEmpty {
return true
}
let intvalue = Int(newStr)
return (intvalue >= 0 && intvalue <= 12)
}
return true
}
Swift : How to get the string before a certain character?
Use componentsSeparatedByString() as shown below:
var delimiter = " "
var newstr = "token0 token1 token2 token3"
var token = newstr.components(separatedBy: delimiter)
print (token[0])
Or to use your specific case:
var delimiter = " token1"
var newstr = "token0 token1 token2 token3"
var token = newstr.components(separatedBy: delimiter)
print (token[0])
How to get first four letters from string in Swift 3?
This is a simple validation using regular expression. The pattern represents:
^
must be the beginning of the string[A-Za-z]{4}
= four characters A-Z or a-z0
one zero.{6}
six arbitrary characters$
must be the end of the string
Updated to Swift 4
func validateIFSC(code : String) -> Bool {
let regex = try! NSRegularExpression(pattern: "^[A-Za-z]{4}0.{6}$")
return regex.numberOfMatches(in: code, range: NSRange(code.startIndex..., in: code)) == 1
}
PS: To answer your question, you get the first 4 characters in Swift 3 with
let first4 = code.substring(to:code.index(code.startIndex, offsetBy: 4))
and in Swift 4 simply
let first4 = String(code.prefix(4))
How do you use String.substringWithRange? (or, how do Ranges work in Swift?)
You can use the substringWithRange method. It takes a start and end String.Index.
var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex)) //"Hello, playground"
To change the start and end index, use advancedBy(n).
var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(2), end: str.endIndex.advancedBy(-1))) //"llo, playgroun"
You can also still use the NSString method with NSRange, but you have to make sure you are using an NSString like this:
let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))
Note: as JanX2 mentioned, this second method is not safe with unicode strings.
Related Topics
Parse Starter Project Login and Register View Controllers Errors
Segues Initiated Directly from View Controllers Warning in Storyboard Xcode
Get Index or Tag Value from Imageview Tap Gesture
Phimageresultisdegradedkey/Phimagefileurlkey Is Not Found
How to Remove the Bottom Gap of Uipageviewcontroller
iOS Web App: Showing Content Only If the Application Is Standalone
Today Extension View Flashes When Redrawing
Extract Last Word in String with Swift
Taking Screenshots in the Background (Ios) - Improving Performance
iOS 7.0 and Arc: Uitableview Never Deallocated After Rows Animation
Physicsbody Doesn't Adhere to Node's Anchor Point
Making Uitableview with Embedded Uicollectionview Using Uitableviewautomaticdimension
How to Take a Snapshot of a Uiview That Isn't Rendered
iOS - Using Storyboard and Autolayout to Center the Uiscrollview