Replace Characters in a Range in Swift - ios

I have a chunk of code that looks like this:
HiClass *myNewClass;
Now, what I'm doing is writing a method to roll through and delete the Hi, as well as everything after it, including the *, so that only myNewClass; is left. Now, I take out the "Hi" like so:
textToConvert = inputField.stringValue.stringByReplacingOccurrencesOfString("Hi", withString: "",
options: NSStringCompareOptions.LiteralSearch, range: nil)
But within this same method, if possible, I would like to somehow delete everything leaving only myNewClass;, as stated above.
My first though on how to approach this is to use a range. Though still being new to Swift and trying to avoid Objective-C, I'm unsure of how to remove all of the characters between the Hi and the *, leaving onlymyClass.

you can use this method
var testStr = "HiClass *myNewClass"
let array = testStr.componentsSeparatedByString("*")
testStr = String(array.last)

You can use indexOf with Swift 2.0 to find the index, and just take a substring to the end of it like this:
var str = "HiClass *myNewClass"
if let idx = str.characters.indexOf("*") {
var s = str.substringFromIndex(advance(idx, 1))
}

Related

substring of the first 4 characters from a textField in Swift 4

I'm trying to create a substring of the first 4 characters entered in a textField in Swift 4 on my iOS app.
Since the change to Swift 4 I'm struggling with basic String parsing.
So based on Apple documentation I'm assuming I need to use the substring.index function and I understand the second parameter (offsetBy) is the number of characters to create a substring with. I'm just unsure how I tell Swift to start at the beginning of the string.
This is the code so far:
let postcode = textFieldPostcode.text
let newPostcode = postcode?.index(STARTATTHEBEGININGOFTHESTRING, offsetBy: 4)
I hope my explanation makes sense, happy to answer any questions on this.
Thanks,
In Swift 4 you can use
let string = "Hello World"
let first4 = string.prefix(4) // Hell
The type of the result is a new type Substring which behaves very similar to String. However if first4 is supposed to leave the current scope – for example as a return value of a function – it's recommended to create a String explicitly:
let first4 = String(string.prefix(4)) // Hell
See also SE 0163 String Revision 1
In Swift 4:
let postcode = textFieldPostcode.text!
let index = postcode.index(postcode.startIndex, offsetBy: 4)
let newPostCode = String(postcode[..<index])

Putting array into label in swift

#IBAction func generateBtn(sender: UIButton) {
let strt = UInt32(strtNum.text!)
let end = UInt32(endNum.text!)
let ttlNums = Int(amtNums.text!)
let x = RandomNum()
var z = 0
while z<ttlNums{
let y = x.rndNumGen(strt!, end: end!)
z += 1
var h = [String]()
h.append(String(y))
let display:String = h.joinWithSeparator(", ")
winningNums.text = display
print (display)
}
}
I don't know what is wrong with this code. I am trying to put the string display into the label and it prints out the last number from the random number generator. When i print it to the console it shows all of the random numbers.
The primary issue here is that your array is created fresh in every loop iteration, and your label is being set in every loop iteration. That means that the array will only ever contain the element made in that iteration, after which it's reset to a new array, and a new element is added. The array needs to be initialized once at the start, and have elements added to it repeatedly in the loop, then put into the label once at the end.
#IBAction func generateBtn(sender: UIButton) {
guard let startText = strtNum.text, let start = UInt32(startText),
let endText = endNum.text, let end = UInt32(endText),
let ttlText = amtNums.text, let ttlNums = UInt32(ttlText) else {
//one of these is nil, handle it gracefully here
return
}
let randomGenerator = RandomNum()
var h = [String]()
h.reserveCapacity(ttlNums)
for _ in 0..<ttlNums {
let randomNum = randomGenerator.rndNumGen(start, end: end)
h.append(String(RandomNum))
}
let display = h.joinWithSeparator(", ")
winningNums.text = display
print(display)
}
I've made a few other changes to bring this code in line with Swift best practices and conventions:
Don't force unwrap. Use an if let or guard let binding to safely handle nil values.
Give your variables meaningful names. Avoid single-letter names except in specific instances.
Don't put spaces beside a function/method name and the proceeding brackets.
Don't use a while loop to iterate over a known range. Instead, use a for in loop.
Dn't type in t3xtspk, it mks ur code look lik an angsty teenagr wrote it. Autocomplete will finish off words for you, so you barely end up typing anyway. Make it easy and readable.
I would suggest you make a few changes yourself:
Rename generateBtn. Functions/methods DO things, they're actions. They should be named with verbs, or verb phrases. Perhaps try something like displayRandomArray.
Refactor the random array generation into its own method.
Rename RandomNum. By the looks of it, it's not a number at all, it's a random number generator. Perhaps try RandomNumberGenerator
Rename h.
Add code to deal with what happens when the .text is nil, or what happens when it contains a string that isn't a UInt32 (thus causing the UInt32 initializer to fail and return nil)

"Cannot Increment endIndex" because of emoji

I have a function that finds the current word a user has selected in a UITextView. However, if I call this function when an emoji is in the UITextView.text property, I see a crash. I believe this is because of the different character counts in String vs NSString.
How do I properly convert this?
func currentWord() -> String {
let cursorPosition = selectedRange.location
let separationCharacters = NSCharacterSet(charactersInString: " ")
// crash occurs here
let beginRange = Range(text.startIndex.advancedBy(0) ..< text.startIndex.advancedBy(cursorPosition))
let endRange = Range(text.startIndex.advancedBy(cursorPosition) ..< text.startIndex.advancedBy(text.characters.count))
let beginPhrase = text.substringWithRange(beginRange)
let endPhrase = text.substringWithRange(endRange)
let beginWords = beginPhrase.componentsSeparatedByCharactersInSet(separationCharacters)
let endWords = endPhrase.componentsSeparatedByCharactersInSet(separationCharacters)
return beginWords.last! + endWords.first!
}
I believe this is because of the different character counts in String vs NSString
You're right about that. You are shifting back and forth between using NSRange (Cocoa) and Range (Swift) — and they work differently. And NSString (Cocoa) and String (Swift) have different ideas of where the character boundaries are. You need to be consistent.
Once you've used selectedRange in the first line, you are in the Cocoa world of NSRange. You need to stay consistently in the Cocoa world. Don't use any Swift Ranges! Don't use any Swift characters!
Form your beginRange entirely using NSRange — for example, call NSMakeRange. Don't use characters.count; stay in the NSString world and use the string's length (in Swift, that is its utf16.count). Then all will be well.

Using lowercaseString in Swift with the "İ" character

In my app, I use lowercaseString. When I change "İ" to lowercase, the output is incorrect. It puts more points on the smaller letters:
let isim = "titTTSSİŞÇÖÜİİİle".lowercaseString
The output is:
titttssi̇şçöüi̇i̇i̇le
The correct output for İ should be i
It looks like this is Turkish text. You can use lowercaseStringWithLocale to handle this correctly:
4> let isim = "titTTSSİŞÇÖÜİİİle".lowercaseStringWithLocale(NSLocale(localeIdentifier: "tr"))
isim: String = "titttssişçöüiiile"
You may wish to use NSLocale.currentLocale instead, to accommodate users in different locales based on their preferences.
You may have to change that character separately. Perhaps something like this:
var isim: NSString = "titTTSSİŞÇÖÜİİİle".lowercaseString
isim = isim.stringByReplacingOccurrencesOfString("İ", withString: "i")
Hope this helps.

Swift 2 NSMutableArray() value don't shows in variable

Swift 2 NSMutableArray() value don't shows in variable
My codes here.
var detail_desc : NSMutableArray! = NSMutableArray()
when i added this code gives me
label.text = self.detail_desc.description
And my array output
{
{
"cat_img" = "http://asdasd.com/asd.jpg";
"cat_name" = Good;
id = 45;
"is_active" = 3;
"last_update" = "2015-11-21 15:32:42";
}
}
I want to use array item to variable ;
label.text = cat_img
label2.text = cat_name
any idea ?
There's a lot wrong with what you have, I'll try to tackle it one by one:
Underscore
Underscore naming isn't common in cocoa and reads very strange. Change detail_desc to detailDesc.
Note: There are situations in which we use the underscore, one of which is extensions on core classes. In these cases, it is prefix - underscore - name. ie: my_specialFunctionOrVariable
NSMutableArray
NSArray and NSDictionary classes shouldn't be used in Swift unless absolutely necessary. They behave slightly differently, and you lose all of the type safety that makes swift so great.
Naming
In general, naming schemes like label, label2, and detailDescription are very confusing. They don't tell me anything about what each represents. Try something like catImageUrlLabel, and catNameLabel to be more specific. Also, detailDescription could be catInformation
Single Object Encapsulated In Array
You really have a dictionary as the single object in an array, I think you should just have the dictionary reference. (unless there could be more in the future). I'll move forward assuming there won't be.
How it might look
Change your variable to something like this:
var detailDescription: [String : AnyObject] = ...
Then, in your UI setting code, do something like this:
label.text = detailDescription["cat_img"] as? String
label2.text = detailDescription["cat_name"] as? String
Modelling Objects
Json is dirty and we prefer not to deal with it as much as possible. Consider modeling your Cat json to a Cat object:
struct Cat {
let imageUrl: String
let name: String
let id: Int
// etc.
}
Then parse the json into this model when you receive it and pass that to your view controller.
Then our code might look like this:
nameLabel.text = cat.name
imageUrlLabel.text = cat.imageUrl
// etc.
This is very clear what everything represents, and will make for a more readable, and more maintainable code base.
Hope this gets you off on the right track.

Resources