Xcode: Two labels, one button - xcode

I am trying to change two labels in one click, without coding.
I don't want to set up it like:
IBOutlet UILabel *label1;
IBOutlet UILabel *label2;
I want to do that in the storyboard with the view controller (i.e., draw a line from the same object to two labels).

You can't reference two labels with the same outlet. If the issue is that you want the text of both labels to be updated when a single NSString value is set you can probably make it observable and on change set the text of both labels.

Related

Drawing with drawRect method - Cocoa

I've been looking for solutions but can't figure out if it is possible to do the following:
I have a drawRect method, what i want to do is to add a graphic element (such as rects and lines) to the current view without refreshing it. I used to call setNeedsDisplay but this method is actually deleting myView an re-drawing it from 0.. Any suggestion to keep the old one and add new content ?
Thank
Every time an update is made in a view the entirety of it is redrawn; so -drawRect needs to redraw the entire view. You have to 'refresh' your view - it's the norm - there's nothing wrong with it. Just draw the old content again.
Or, you could call setNeedsDisplayInRect: if you do want to just redraw a specific section of your view.
That's what drawRect: does - it redraws the rect in the view.
If you want lines and rects drawn on top, try doing it on a different layer.
I guess it's better if you work with layers.
You can make CALayer subclasses for your shapes, and then save them in an array.
By default , the drawRect method will clear the whole content , if your want to dynamic draw some new graphics contents to the view ,you should abstract these graphics element's data structure , for example , you add a line ,this line will have
a start point
a end point
line color
line width
is has a shadow
a line join
so you can put all these property into a struct and define a new Data Class named LineStruct and define a method called
-(void)drawLine:(CGContextRef)ctx withLineStruct:(LineStruct*)lineStruct
to your custom UIView , define a
#property (nonatomic) LineStruct *lineStruct ;
and invoke in it's drawRect method
-(void)drawRect:(CGContextRef)ctx{
CGContextRef ctx = UIGraphicsGetCurrentContext() ;
[self drawLine:ctx withLineStruct:self.lineStruct];
}
so if your have other graphic contents , you can do the draw like that . If you have lots of
contents , you must add a buffer to your UIView ,such as add a NSArray , and in the drawRect method ,you add a for(;;)to draw all the graphics elements
I think maybe you need something like an NSBezierPath to store all your shapes and add new shapes. It's easy to add new shapes to an existing NSBezierPath, see the documentation: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSBezierPath_Class/Reference/Reference.html
Then in your drawrect, you will only have to stroke or fill the NSBezierPath.
This will only work if all your shapes have the same fill color and stroke. Otherwise you could keep some kind of list of multiple NSBezierPaths and stroke/fill them in different ways.
You can 'get around' this by making the view you want to draw in separate from your view with the original iboutlets. Then make your main view background transparent (but do not make the iboutlets transparent). So for this example, I will prevent that the IBOutlets you want to keep (not draw over) are a UITextField, a UILabel and a UIButton.
So you Interface Builder will look like this:
UIVIewController
UIView2 (view with drawRect defined)
UIView (main)
UITextField
UILabel
UIButton
So as you see, when you call 'drawRect' it will still blank out your UIView2 completely, but it won't matter because 'drawRect' won't delete any of the UILabel, UIButton, UITextField or whatever else you want to keep in your UIView1. Hope this helps.

Xcode 4.3: duplicated connections of an IBOutlet

I am learning Stanford CS193p course with Xcode 4.3.3. I think the screenshot below is pretty much self-explaining. But i will describe the problem with words anyway.
I control-drag a UILabel from storyboard to corresponding implementation file to make the IBOutlet #property. Then I see two connections displayed when clicking the filled circle in the left side of the editor where shows line numbers. I don't know how to delete it.
Moreover, I see only ONE connection in storyboard's connections inspector of the UIlabel.
More weird, when I try to set the UILabel's text inside the setter of a public preperty, it fails to update the label's text:
-(void) setQuestion:(NSString *)question
{
_question = question;
self.questionLabel.text = question;
NSLog(#"The quesion is %#",question);
NSLog(#"The quesion label text is %#",self.questionLabel.text);
}
I use two NSLog to debug and get the following. It shows the NSString *question is #"What do you want your label to say?", yet the self.questionLabel.text is null. The value assign fails. I suspect this relate to the duplicated connections thing mentioned above.
2012-07-29 04:03:53.817 Kitchen Sink[18628:f803] The quesion is What
do you want your label to say?
2012-07-29 04:03:53.820 Kitchen
Sink[18628:f803] The quesion label text is (null)
The following is the screenshot showing the duplicated connections. I am probably missing something obvious, please help.
I would stalk this up to Xcode storyboard wonkiness.
First, try a clean of the project and a re-build.
Should you still have that problem, manually define the #property without dragging from the AskerViewController view to the AskerViewController implementation (.m) file by doing the following.
Cut that IBOutlet #property line in the interface section of the implementation (.m) file for AskerViewController. Click the label in storyboard. Disconnect any binding that label to the AskerViewController. Clean the project. Then, paste back in the property, and control-drag from the label to the view controller orb at the bottom of the AskerViewController view in your storyboard file.

UITextField text not changing on the UI

Once the code bellow is executed, the textfield's text doesn't change in the UI to "Fly" but the second NSLog does print "TextField: Fly" as it should.
#property (strong, nonatomic) IBOutlet UITextField *typeTextField;
....
UITableViewCell* cell = [self.theTableView dequeueReusableCellWithIdentifier:#"TypeCell"];
self.typeTextField = (UITextField*)[cell viewWithTag:1];
NSLog(#"TextField: %# ", self.typeTextField.text);
self.typeTextField.text = #"Fly";
NSLog(#"TextField: %# ", self.typeTextField.text);
Any help would be much appreciated.
You almost definitely forgot to connect the outlet for the UITextField in interface builder. Bring up the .xib file that that typeTextField is visible in, click on typeTextField, then show the Utility pane (the one on the far right in Xcode 4+). Click the Connections Inspector (the one that looks like a right arrow) and drag a New Referencing Outlet to your File's Owner.
When you don't connect the UITextField you drew in Interface Builder with the IBOutlet that you identified in your source file, both UITextFields get created as separate entities. You can make changes and work with the valid typeTextField with a broken IBOutlet, but it'll never appear on your view.
Consult How to connect an IBOutlet from an UITableViewController directly to custom cell? and http://www.youtube.com/watch?v=d_kO-J3DYvc on properly wiring your custom UITableViewCell objects.

How to add text to NSTableView

I made a Cocoa application that has an NSTableView, an NSTextField, and an NSButton. The user enters text into the text field and clicks the button. When the user does this, I want the text in the textfield to be placed in the NSTableView. I find that I can't even bind an IBOutlet to a cell in the NSTableView. What should be done?
The Model-View-Controller pattern, which is used extensively in Cocoa is your friend here.
What you need to do is to bind the NSTableView to an array (The model). Then configure the button so that a click tells the controller to add the content of the text field to the array and if the bindings are set up correctly the NSTableView (The View) will be updated.
What I think you need to do is make a class, AppController for instance which will be your data source and the delegate of the NSTableView. So you need the following.
Two IBOutlets (one for the NSTextField and one for the NSTableView)
An IBAction for the NSButton.
Make those connections in Interface Builder.
Remember to use the mandatory delegate methods (there are two of them) so you can add the data from your data source (usually a collection class..an array, dictionary...etc.

One IBOutlet for two UILabels

I have two views within one .xib (one view for landscape, another for portrait). How can I use the same IBOutlet I've defined in #interface section for both labels if they have the same functionality. (ctrl+dragging to both of them does'n help-each time I drag to second, the first one loses its outlet).
You can't. IBOutlet is an (UILabel?) object that must store reference to UI element. Naturally single object cannot reference to two different objects.
Yes, of-course you can do this using IBOutletCollection instead of IBOutlet.
IBOutletCollection(UILabel) NSArray *labels;
Use the array to access all labels at runtime.

Resources