I thought this would be a no brainer, but it turns out I have spent about 5 hours on this now.
I have two ViewControllers and I want to pass a pre formatted NSString to another VC, using a IBAction called putInfo. All this action is responsible for is putting a word into a label on another VC, .
so, in the first ViewController, I implemented the code like this :
- (IBAction)putInfo:(id)sender {
((secondViewController *)self.presentingViewController).ouputLabel.text = #"chicken";
}
I have tried other things like-grabbing a reference to the second VC, instantiating the second view controller, doing that thing where you initialize the second VC WithNibName--all that. ABove is just my latest failure.
This seems like it should be such a no brainer. any suggestions?
If you're using Storyboard, you'll need to use the method prepareForSegue.
But first you need to put a name to your segue: click on it, go to Attribute Inspector and write an Identifier name for the segue.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier]isEqualToString:#"mySegue"])
{
secondViewController* second = segue.destinationViewController;
second.outputLabel = txtFieldSecondViewController;
}
}
You pass the value of a textField(or some string) to another NSString object of the second view.
Related
I want to update the column width to the width of the widest entry whenever a node in my NSOutlineView is expanded. Thus, my delegate listens to outlineViewItemDidExpand and calls
[column setWidth:maxColumnWidth];
in it. maxColumnWidth is the width of the widest entry.
However, for some reason, calling setWidth from inside outlineViewItemDidExpand doesn't seem to do anything. When I call it later, e.g. as a response to a button click, it works just fine, but from within outlineViewItemDidExpand it just does nothing.
So any idea what I could do to update the column width whenever the user clicks on an expander icon? Thanks a lot!
If autoresizesOutlineColumn is YES (default) then the outline view resizes the outline column after outlineViewItemDidExpand. Solution: set autoresizesOutlineColumn to NO.
I was able to solve this by calling setWidth() from a selector called by performSelector() from within outlineViewItemDidExpand, like so:
-(void) setColumnWidth
{
[theColumn setWidth:...];
}
-(void) outlineViewItemDidExpand:(NSNotification*)notification
{
// calling setWidth() here doesn't work
// [theColumn setWidth:...];
// but calling setWidth() from a selector works!
[self performSelector:#selector(setColumnWidth) withObject:nil afterDelay:0.0];
}
Don't ask me why calling setWidth() only works from within a selector but it actually does...
I have a small xib, Teste.xib
owned by TesteView
class TesteView: UIView {
#IBOutlet var tf:UITextField!
#IBOutlet var sw:UISwitch!
}
Now, we're gonna load it (and for example stuff it in a stack view).
let t:TesteView = TesteView()
let v = Bundle.main.loadNibNamed("Teste", owner: t, options: nil)?[0] as! UIView
v.heightAnchor.constraint(equalToConstant: 200).isActive = true
stack?.insertArrangedSubview(v, at: 3)
in fact, that's fine.
Everything works.
But note that you insert "v", not "t". "v" is not "the TesteView", it's just some damned view that is floating around.
If you do the following,
t.heightAnchor.constraint(equalToConstant: 200).isActive = true
stack?.insertArrangedSubview(t, at: 3)
it is meaningless, that doesn't work.
But t "is" the view, it's a UIView (indeed, it is a TesteView). It should be the thing you insert.
So you have to use the "two different" things ...
t.tf.text = "WTF???"
// use "t" for that sort of thing
v.heightAnchor.constraint(equalToConstant: 200).isActive = true
v.backgroundColor = UIColor.blue
// but use "v" for that sort of thing
stack?.insertArrangedSubview(v, at: 3)
It seems weird that "t" and "v" are not the same.
(Indeed, should TesteView even have been a subclass of UIView? Maybe it should be something else - just a plain class?? It seems one can not really use it as a view so WTF is it??)
What's the deal on this and/or what is the usual idiom?
NOTE ...
nowadays, there is no reason to ever do this. Just use a small UIViewController. For decades everyone said "Why doesn't apple let you simply load a view controller by id?", well now you can. No problems:
let t = self.storyboard?.instantiateViewController(withIdentifier: "TesteID") as! Teste
t.view.heightAnchor.constraint(equalToConstant: 200).isActive = true
stack?.insertArrangedSubview(t.view, at: 3)
t.tex.text = "WTH???"
This code makes no sense; your use of t is pointless:
let t:TesteView = TesteView()
let v = Bundle.main.loadNibNamed("Teste", owner: t, options: nil)?[0] as! UIView
The object of nominating an owner is to provide some already existing instance with properties that match outlets in the nib. This allows the outlets to be used, and the views to which they lead can immediately be referred to by name.
That is what happens when a view controller / view pair is loaded from a storyboard, and is why storyboards work the way they do. The view nib is loaded with the view controller as owner. So if the view nib has outlet mySwitch and the view controller has outlet property mySwitch, they match up and the term self.mySwitch can be used by the view controller instance to refer to the switch.
You can arrange the same thing yourself when loading a .xib file. But you are not doing that; your code is just deliberately silly.
For example (this is from my book, and you can download and run the example for yourself):
class ViewController: UIViewController {
#IBOutlet var coolview : UIView!
override func viewDidLoad() {
super.viewDidLoad()
Bundle.main.loadNibNamed("View", owner: self)
self.view.addSubview(self.coolview)
}
}
If you have configured View.xib with its File's Owner proxy's class set to ViewController, and if you've then drawn an outlet from the File's Owner to the view and named that outlet coolview, when we load it is matched with the coolview property and the last line works — we can refer to the nib-loaded view as self.coolview.
And notice, please, that we never had to capture the result of loading the nib as an array of views and then refer to element zero of that array, as you do. The view gets slotted right into the name coolview. That is how you load a nib so as to get a useful name or names.
I just want to add a NSButton with setAction Arguments.
NSRect frame = NSMakeRect(10, 40, 90, 40);
NSButton* pushButton = [[NSButton alloc] initWithFrame: frame];
[pushButton setTarget:self];
[pushButton setAction:#selector(myAction:)];
But I want to put an argument to the function myAction...
How ?
Thanks.
But I want to put an argument to the function myAction...
How ?
You can't.
… if there is more than one button that uses this method, we can not differentiate the sender (only with title)...
There are three ways to tell which button (or other control) is talking to you:
Assign each button (or other control) a tag, and compare the tags in your action method. When you create controls in a nib, this has the downside that you have to write the tag twice (once in the code, once in the nib). Since you're writing out the button by hand from scratch, you don't have that problem.
Have an outlet to every control that you expect to send you this message, and compare the sender to each outlet.
Have different action methods, with each control being the only one wired up to each action. Each action method then does not need to determine which control sent you that message, because you already know that by which method it is.
The problem with tags is the aforementioned repetitiveness. It's also very easy to neglect to name each tag, so you end up looking at code like if ([sender tag] == 42) and not knowing/having to look up which control is #42.
The problem with outlets is that your action method may get very long, and anyway is probably doing multiple different things that have no business being in the same method. (Which is also a problem with tags.)
So, I generally prefer the third solution. Create an action method for every button (or other control) that will have you as its target. You'll typically name the method and the button the same (like save: and “Save”) or something very similar (like terminate: and “Quit”), so you'll know just by reading each method which button it belongs to.
I never programatically created an NSButton, but I think that you just need to create a method like this:
- (void) myAction: (NSButton*)button{
//your code
}
And that's it !!
You can use associated Objects for passing arguments.
You can refer : http://labs.vectorform.com/2011/07/objective-c-associated-objects/
http://www.cocoanetics.com/2012/06/associated-objects/
.tag should be sufficient if your object have any integer uniqueID.
I use .identifier instead, since it support string based uniqueID.
Example:
...
for (index, app) in apps.enumerated() {
let appButton = NSButton(title: app.title, target: self, action: #selector(appButtonPressed))
appButton.identifier = NSUserInterfaceItemIdentifier(rawValue: app.guid)
}
...
#objc func appButtonPressed(sender: NSButton) {
print(sender.identifier?.rawValue)
}
I am using a UIPickerView and currently their is only a single object in it. How can I display that single object on label.
It has this weird property that when we use pickerView the data is not set selected by default.Once we choose another object or roll it, then only any particular object is selected. Hence if only one object is their in pickerView. It does not count as selected even though when you tap on that single object.
I tried a lot but found that if their are more than one object then only you can display the selected object on label but not if their is only one object.
You need to make a code that is triggered when the UIPickerView changes, like this:
#pragma
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
//Action that triggers following code:
{
NSString *nameString = [nameOnMutubaleArrayYouWannaGetDataFrom objectAtIndex:[picker selectedRowInComponent:0]]; //Or 1 if u have multiple rows
NSString *labelString = [[NSString alloc]initWithFormat:
#" %# ", nameString];
labelOutput.text = labelString;
Hope this helps.
I want to pass the value entered in a UITextfield into another view. and this value shud appear in the UItextfield of second view. IBoutlet,propery,synthesize everything is written correctly. still i am not getting the value in the second view.
My code,
from first view it is passing like this
firstview.txtname1.text=name1.text;
from second view it is accepting like this
player_name1.text=txtname1.text;
can anybody tell me where i went wrong?
First you have to declare the property and synthesize in the secondviewcontroller.
in secondview.h
#property(nonatomic,retain) NSString *str;
in secondview.m
#synthesize str;
And then when you are going from first view to second view do like this.
secondviewobj.name = textfield.text;