Objective C unable to update UILabel more than once - objective-c

I have a method which I created that appends some new text to a UILabel. I've tried two ways of doing this (one is commented out) but both of them only update the label the first time. Any more calls to this method do not update the label.
- (void) updateLog: (NSString*) text
{
/*
NSMutableString *newText = [logLabel.text mutableCopy];
[newText appendString: text];
logLabel.text = newText;
*/
logLabel.text = [logLabel.text stringByAppendingFormat:#"%#", text];
}
I am calling the method like this (the method is in the viewController):
[viewController updateLog: #"\nStarting...\n"]; // Works
[viewController updateLog: #"Test\n"]; // Does not work
I have searched everywhere for an answer, what am I missing? Thanks!

UILabel, unless set up otherwise, only displays a single line of text.
Change the numberOfLines property if you want more.

I actually figured this out. Turns out the string WAS being successfully updated, but the label size was too small, so the text was hidden.

Related

How do I concatenate strings together in Objective-C?

So I am trying to concatenate a bunch of input strings together as one string so I can save that to a text file.
So far I am trying to write something like this
NSString *tempString = [[NSString alloc]initWithFormat:#"%#%#%#", text1, text2, text3];
The only problem with this is that I need a total of 30 strings stored this way. I need a way to do this without typing out each string name. Is there a way to use a for loop or something to accomplish this? Type the strings like this perhaps?
text(i)
So that the variable name would change each time it went through the for loop. I've tried doing something like this and I can't get it to work. If you can help me with this method or another way that you know to do it I would be very thankful.
Okay, so all of the answers here take the wrong approach (sorry guys).
The fundamental problem is that you are using your "text boxes" as a data source, when they should simply be views. When someone changes the text, you should immediately store them in your model (which could be a simple array) and then reference that model later. (This is part of MVC. Look it up if you aren't familiar, as you should be if you are programming for iOS!)
Here is what I would do. (I'm assuming that your "text boxes" are UITextField's.)
Set the delegate for each text field to your view controller.
Set the tag for each text field to a number which represents the order that you want the strings joined in. (ie 1-30)
If you don't have a separate class for your data model, then setup a declared property in your view controller which stores a reference to a NSMutableArray which can contain all of the strings in order. Let's call it dataSource. In viewDidLoad: set this to an actual mutable array filled with empty values (or previously stored values if you are saving them). The reason that we store empty values is so that we can replace them with the user entered strings for any index, even if they are entered out of order:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = [[NSMutableArray alloc] initWithCapacity:20];
for(int i = 0; i < 30; i++)
[self.dataSource addObject:#""];
}
Then, use the following text field delegate method which stores the strings into the array as they are entered:
// This is called every time that a text field finishes editing.
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField.tag > 0)
[self.dataSource replaceObjectAtIndex:textField.tag-1 withObject:textField.text];
}
Congratulations! All of your strings are now stored in one array. Now we just have to combine them all:
NSMutableString *theString = [self.dataSource componentsJoinedByString:#""];
Note that I have NOT tested all of this so there may be typos. This should get you pointed in the right direction though!
If you set up your text boxes in Interface Builder with an IBOutletCollection(UITextField) you would have an array of text boxes that you could access the text value using KVC and join them.
//interface
...
#property (nonatomic, strong) IBOutletCollection(UITextField) NSArray *textBoxes;
//implementation
...
NSString *tempString = [[textBoxes valueForKey:#"text"]
componentsJoinedByString:#""];
Using iOS 4's IBOutletCollection
If you programmatically create your text boxes then add them to an array as you create them.
NSMutableString's appendString: method is your friend.
NSArray *strings = [NSArray arrayWithObjects: #"Hi", #" there", #" dude", nil];
NSMutableString *result = [[NSMutableString alloc] init];
for (NSString *string in strings) {
[result appendString:string];
}
NSLog(#"result: %#", result); // result: Hi there dude

The difference between how arrays are populated in ios?

Hello and Thanks to All,
Here is the situation, When I use the following methode to populate my array it works when I use Methode 2 it does not work. The objective is to change the color of text. Both Methods have been NSLOGED and the data is identical.
First way..(working name gets grayed out)
-cellForRowAtIndexPath
....
if ([self.secArray containsObject:indexPath]) {
cell.textLabel.textColor = [UIColor grayColor];
} .....
-didSelectRowAtIndexPath:
...
[secArray addObject:indexPath];
Second Way (not working - populate the Array from my .plist )
-cellForRowAtIndexPath
....
if ([self.secArray containsObject:indexPath]) {
cell.textLabel.textColor = [UIColor grayColor];
} .....
-viewWillAppear
NSString *filePathOrdersIndex = [self dataFilePathOrders];
NSMutableArray *chekDist;
chekDist = [[NSMutableArray alloc] initWithContentsOfFile:filePathOrdersIndex];
NSLog( #"data checkDist........... %#", chekDist);
if(!chekDist){
chekDist = [[NSMutableArray alloc]init];
}
for(id dist_data in chekDist){
secArray = [dist_data objectForKey:#"myIndexPath"];
//[secArray addObject:[dist_data objectForKey:#"myIndexPath"]];
}
both methods logged to console both arrays contain Identical array data....but second way is not working
any help is greatly appreciated.
In the second method, you are assigning an element of the checkDist array to the array itself, is each dist_data in checkDist a secArray?
From an outside perspective, these two methods are not functionally equivalent without knowing more information about what kinds of data these variables hold. Though since you are setting the secArray variable each time the for loop executes, I'm assuming this is incorrect and you need to use the line you had commented-out in your second method ([secArray addObject:[dist_data objectForKey:#"myIndexPath"]];).
If after using that line instead it is still not working, verify that secArray has been created (make sure it's not nil) when the second method executes.

String Problems

A very stupid question from a noob.
I have an action, that sets the string of a label.
- (IBAction) changeProductText:(NSString *)str{
lblProductTxt.text = str;
}
This is the string I want to set that to:
TestText = [NSString stringWithFormat:#"Hi"];
And this is how I am doing it:
[self.navigationController pushViewController:nextController animated:YES];
[nextController changeProductText:TestText];
My problem is that it wont set the string to anything is random whats going into the string. It may crash when I click on the cell it may not, so I am doing something wrong.
stringWithFormat gives you an autoreleased format, without seeing more of the code I'm guessing its hitting an autorelease pool and you're trying to access garbage that was your string.
Is this the exact sequence of the statements?
[self.navigationController pushViewController:nextController animated:YES];
[nextController changeProductText:TestText];
I am not 100% sure but I believe that the second line will not be executed before the nextController is being pushed.
Try to reverse them.
(1st create and initialize the nextController)
2nd assign all values that you want to pass down to nextController
3rd push nextViewController on the stack of View Controllers.
[nextController changeProductText:TestText];
[self.navigationController pushViewController:nextController animated:YES];
The only parameter of an IBAction is the sender:
- (IBAction) clickMyButton: (id) sender;
A string is hardly a valid sender for an action, so whatever you are setting to lblProductTxt.text, it is not a string, it is the sender that performs the action.
In your action method, you can of course set lblProductTxt.text. You'll have to find out yourself where you get the string.
Update
From your comments I deduce you don't have an IBAction, you simply have a void method. Your use of IBAction got me on the wrong foot. Declare it like:
- (void) changeProductText: (NSString *) newText;
Omit the (IBAction) designator, as that is only necessary for, well, real IB action methods.
No matter if you use
NSString *testText = [NSString stringWithFormat: #"Hi"];
or
NSString *testText = [NSString stringWithString: #"Hi"];
The result is exactly the same: an autoreleased NSString with the text "Hi". Only the way it was created is slightly different. If one works and the other crashes, then the same thing is wrong and you are just lucky it doesn't crash.
Now what is wrong is impossible to see from what you posted so far.

Drag and drop between nstableviews in nscollectionview sets window controller property to nil?

In the main window of my application, I have a collection view such that each collection view item contains an NSTableView. The window controller for this window has an NSString * property projecttitle. This property is bound to an NSTextField in the window for which I have overridden the default return key behavior so that the user can hit Return and write a carriage return into the text field. Now, after changing the string in the text field and THEN dragging an item between the table views for two different collection view items, the projecttitle property becomes nil. I sort of feel like maybe I just have way too much going on here and that this bug will be impossible to track down, but maybe someone has seen something even remotely similar to this behavior elsewhere?
EDIT: Putting a breakpoint on the projecttitle property doesn't seem to yield anything useful. The program execution does not break at all upon dragging and dropping, but the property will indeed be nil after this.
EDIT 2: After more digging around, it appears the behavior is related to the NSFormatter object. It happens not only when dragging and dropping, but apparently any time the nstextfield attempts to resign as responder. This behavior stops when I disconnect the formatter object in IB. Here's the string validation code for the formatter which forces the string to be less than or equal to 4 lines long and with each line being no longer than 32 characters. This seems to work fine when actually typing the in the text field, but apparently, not after.
-(BOOL)isPartialStringValid:(NSString **)partialStringPtr
proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
originalString:(NSString *)origString
originalSelectedRange:(NSRange)origSelRange
errorDescription:(NSString **)error {
NSArray * lines = [*partialStringPtr componentsSeparatedByString:#"\n"];
if ( [lines count] > 4 ) {
return NO;
}
for (NSString * line in lines) {
if ( [line length] > self.maxlength ) {
return NO;
}
}
return YES;
}
Okay, solved. Turned out it was the -getObjectValue:forString:errorDescription: method. I had it implemented as
-(BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error {
*obj = string;
return YES;
}
Changing *obj = string to *obj = [NSString stringWithString:string] fixed everything right up.

How to find the text in an NSTextView?

I need to find the text in an NSTextView, and save it to a file. I can do the saving fine. I have used -stringValue, and -textStorage so far, but neither have worked. When I put -stringValue in, it just gave me (null), and when I put -textStorage in, it gave me a very large chunk of nothing (like a long paragraph of invisible text).
How can I put the text from an NSTextView into an NSString?
Try
NSString *text = [[myTextView textStorage] string];
The NSTextStorage inherits from NSMutableAttributedString which inherits from NSAttributedString. The latter implements the string method.
This isn't too obvious if you just look at the NSTextView's instance methods in the documentation.
Try this:
[myTextView string];
If you are struggling to write the textView stringValue into a file try something like this:
[[myTextView string] writeToFile:#"someFile" atomically:YES encoding:NSUnicodeStringEncoding error:&error];
Hope this helps!
when setting value, use text.string = #"XXXX";
when getting value, use STRING = [text.string copy];
because if you forget copy, the mutableString will be deliver to STRING. This will raise bugs when you editing multiple things with a single textview.
In order to compile all of the information for anyone else with this question, I am answering my own question. If I am not allowed to do this, please tell me.
The code is actually extremely simple.
Files.h
#import <Cocoa/Cocoa.h>
#interface Files : NSObject {
IBOutlet id dataToSave;
}
- (IBAction) saveData: (id) sender;
Files.m
#implementation Files
- (IBAction) saveData: (id) sender; {
NSString *text = [[dataToSave textStorage] string];
NSLog(#"%#", text);
[text writeToFile:#"Users/justin/Desktop/test.txt atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}
Instead of voting this up, vote for the other two people that answered this.