How to find and replace UILabel's value on a specific line? - ios

I know I can find the total number of lines of a UILabel with .numberOfLines but how can I retrieve and edit the value say on line 2.
Example:

Assuming from your screen shot that each line is separated by a newline character you can split the text based on that.
Here is an example in Swift 3:
if let components = label.text?.components(separatedBy: "\n"), components.count > 1 {
let secondLine = components[2]
let editedSecondLine = secondLine + "edited"
label.text = label.text?.replacingOccurrences(of: secondLine, with: editedSecondLine)
}
You should make sure there is a value at whatever index your interested in. This example makes sure that there are more than a single component before retrieving the value.
You can then replace the second line with your edited line.
Hope that helps.

Related

I need to highlight word by word

I've an app in which I need to highlight words. It's like audio books which reads & highlight arabic text.
There are methods to highlight a particular sub-string from label but I don't want that. I want to something like. Lets consider following sentance.
"I am an iOS Developer & I work in BEE Technologies"
Now, what I want, I would say, highlight character number
1-1, -> I
3-4, -> am
6-7, -> an
9-11, ->iOS
13-21, ->Developer
Because I don't think there is any way to simply keep highlighting word by word till end of line.
This is a generic solution, it might be not the best one, but at least it works for me as it should...
I -almost- faced the same case, what I did to achieve it (consider that these are steps to do):
Creating an array of ranges: I calculated the ranges of each word and add them to an array to let it easier when determining which word (range) should be highlighted. For example, when you to highlight "I", you should highlight the range which is at 0 index and so on...
Here is an example of how you can generate an array of NSRange:
let myText = "I am an iOS Developer"
let arrayOfWords = myText.components(separatedBy: " ")
var currentLocation = 0
var currentLength = 0
var arrayOfRanges = [NSRange]()
for word in arrayOfWords {
currentLength = word.characters.count
arrayOfRanges.append(NSRange(location: currentLocation, length: currentLength))
currentLocation += currentLength + 1
}
for rng in arrayOfRanges {
print("location: \(rng.location) length: \(rng.length)")
}
/* output is:
location: 0 length: 1
location: 2 length: 2
location: 5 length: 2
location: 8 length: 3
location: 12 length: 9
*/
Using Timer: to keep checking what is the current second (declare a variable cuurentSecond -for example- and increment it by 1 each second). Based on what is the current second, you can determine which word should be highlighted.
For example: let's say that "I" should be highlighted between 0 and 1 second and "am" should be highlighted from 2 to 3 second, now you can check if the cuurentSecond between 0 and 1 to highlight "I", if it is between 2 and 3 to highlight "am" and so on...
Using NSMutableAttributedString: you should use it to do the actual highlighting for the words (ranges as mentioned int the first bullet). You can also check these questions/answers to know how to use it:
iOS - Highlight One Word Or Multiple Words In A UITextView.
How can I change style of some words in my UITextView one by one in Swift?
Hope this helped...

Cannot call value of non-function type double

I am quite new to programing in swift and I am working on a music app for iOS that adjusts the font size of the text in a UILabel in proportion to the string's length. In my code, I am trying to count the number of characters in the string statement and have it plugged into a formula, but for some reason Xcode gives me the error: Cannot call value of non function type double I tried setting the value to a CGFloat but it still gives me the same error on the "let b = 41.2 - .8(a) line. Thank you so much and sorry if this seems like a basic question.
let title = "Let It Bleed"
AlbumName.text = title
let a = title.characters.count
if ( a <= 19){
let b = 41.2 - .8(a)
let fontsize = CGFloat(b)
AlbumName.font = AlbumName.font.fontWithSize(fontsize)
}
A screenshot of the code with the error
I assume you expect "0.8 times a" with .8(a).
Three things:
You need leading 0 to represent fractional values in Swift.
You need explicit operator * for multiplication.
You need to convert numeric types to match for mathematical operations.
All these included, your line of interest becomes like this:
let b = 41.2 - 0.8 * CGFloat(a)

Stubborn emoji won't combine: πŸ‘¨β€β€β€πŸ’‹β€πŸ‘¨

Even after #user3441734 solved most of my problems πŸ™‡, there are a few emoji that I can't seem to render properly when converting from a [String:String] to String.
Here's some Playground-ready code to illustrate the problem:
var u = ""
u = "1f468-1f468-1f467-1f467" // πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘§
//u = "1f918-1f3ff" // 🀘🏿
//u = "1f468-2764-1f48b-1f468" // πŸ‘¨β€β€β€πŸ’‹β€πŸ‘¨ (broken)
//u = "1f3c7-1f3fb" // πŸ‡β€πŸ» (broken)
let unicodeArray = u.characters.split("-")
.map(String.init)
.map {String(UnicodeScalar(Int($0,radix: 16) ?? 0))}
if let last = unicodeArray.last {
let separator: String
switch (unicodeArray.first, last) {
// Failed attempt to get tone applied to jockey
case let (horse_racing, _) where horse_racing == "\u{1f3c7}":
separator = "\u{200d}"
case let (_, tone) where "\u{1f3fb}"..."\u{1f3ff}" ~= tone:
separator = ""
case let (_, regionalIndicatorSymbol) where "\u{1f1e6}"..."\u{1f1ff}" ~= regionalIndicatorSymbol:
separator = ""
default:
separator = "\u{200d}"
}
print(unicodeArray.joinWithSeparator(separator))
}
Uncomment each assignment to u in turn to see the problem in action. The 3rd and 4th values should render like so:
and
Thoughts…
It turns out that a long-press on the race horse fails to show skin tones on iOS, so let's assume that's just an oversight, perhaps related to the near-impossibility of judging the jockey's skin tone at standard emoji sizes. I still can't figure out the problem with u = "1f468-2764-1f48b-1f468"
Apologies if this question comes out at all unclear. Chrome and Safari have different behaviors w.r.t these combo-emoji, so only the linked images are guaranteed to appear to you the way I see them on my end. 😒
These emoji are all either skin-tone renderings or tokens of same-sex affection. Is there some sort of bizarre latent racism & homophobia lurking in the system?! 😱 (Cue the conspiracy theories.)
Note that my attempt to use the zero-width joiner, u{200d} didn't help.
So, bug in Apple & Chrome's handling of certain emoji, or is there yet another idiosyncrasy of the standard that I've missed?
There's no conspiracy, the bugs are in your code.
The first character can be produced with:
U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468
Note the ZERO WIDTH JOINER (U+200D) between each character, and the VARIATION SELECTOR-16 selector (U+FE0F) on the HEAVY BLACK HEART (U+2764) to ensure the emoji presentation style is used.
Refer to this table for a complete list of implemented multi-person groupings.
U+1F3C7 HORSE RACING is not an emoji modifier base, and so it does not support skin tone modifiers.

How to set maximum length for UILabel?

In Objective-C, I am attempting to set a limit of character length for a UILabel, but I could not find a way anywhere. For example, a line of text is entered into the UILabel, say 100, but if the maximum character length is set to 50, I just want it to cut off at 50 exactly and not even truncate. I just would like for it to cut off once it hits the limit.
I have tried this; but it didn't work:
NSString *string = my_uilabelText;
if ([string length] >74) {
string = [string substringToIndex:74];
}
Any insight or help would be greatly appreciated. Thank you
Based on your comment, what you actually implemented would work. You just have to ensure your syntax is correct.
Assuming your getting a string from a database:
NSString *string = stringFromDatabase;
//execute your conditional if statement
if (string.length > 50) { //meaning 51+
/* trim the string. Its important to note that substringToIndex returns a
new string containing the characters of the receiver up to, but not
including, the one at a given index. In other words, it goes up to 50,
but not 50, so that means we have to do desired number + 1.
Additionally, this method includes counting white-spaces */
string = [string substringToIndex:51];
}
Then we must set the labels text, this doesn't happen autonomously. So completely:
NSString *string = stringFromDatabase;
if (string.length > 50) {
string = [string substringToIndex:51];
}
self.someUILabel.text = string;
I think the way you are doing it is probably not user friendly. You're getting the string of a UILabel that already has text set and then resetting it. Instead, you should set the desired text to the UILabel before it is called by the delegate

trying to add number to number allready saved on label

So I have a TextField integer that needs to be added to a label.
For example when I type 20, it appears in the label and when I save it and come back it's still there, so far so good right, i got this part down.
Now lets say I come back and want to add another amount to whats already there, to the 20. how exactly would I go about doing it?
I used the NSUserDefaults to load/save the data but when I go to update the label I get stuck when trying to use my variables, say: currentValue, valueToAdd and valueTotalAfterAddition.
You have to get the intValue of the text, and then add whatever number. Example
int currentValue = textField.text.intValue;
int valueToAdd = 10; //change this to whatever you need
int valueTotalAfterAddition = currentValue + valueToAdd;
label.text = [NSString stringWithFormat:#"%d", valueTotalAfterAddition];

Resources