Getting objects like button from view. iOS - objective-c

I created a button in my cover.h file for my first view
#import <UIKit/UIKit.h>
#interface cover : UIViewController
{
IBOutlet UIButton *Enter;
}
#property (nonatomic, retain) UIButton *Enter;
-(IBAction)buttonpressed:(id)sender;
#end
and connected it with the actual button in the inteface builder by choosing File's Owner in the tiny box that gives you the choice of File's Owner, First Responder, and View
Then I went to cover.m file and added the following code
-(IBAction)buttonpressed:(id)sender
{
[[NSBundle mainBundle] loadNibNamed:#"nextView" owner:self options:nil];
NSLog(#"pressed");
}
SO when I go to the nextView.xib and modify nextView.m and nextView.h and access its buttons and do the same thing I did for cover.xib cover.m and cover.h , it doesn't work properly.
What happens is that when I click the enter button in the cover view it shuts down the app. This does not happen until I connected the button to function and outlet (Meaning when it was just switching views and the second view wasn't doing anything it would work)
Thank you for any help you can give. Sorry if I haven't given enough information, kinda new at this, but as find out more info I should have had, I will add it.
Thank you
Edit 1 :
I did not notice anywhere where it said there was an error or anything like that. It built correctly

It's convention to capitalize class names. I'd Suggest CoverViewController. This makes it more obvious, when reading your code, what we're looking at.
What is your intent here? To show nib after nib of content?
Is the "files owner" of every nib a CoverViewController?
What you have actually done is (catastrophically) reloaded the views for the existing controller. This will not end well.
What you want to do is create another instance of the same class:
-(IBAction)buttonpressed:(id)sender {
CoverViewController nextController = [[CoverViewController alloc] initWithNibName:#"nextView"];
[navigationController pushViewController:nextController animated:NO];
}
If you're not using a nav controller, you probably want to be.
Read up on the View Controller Programming Guide.

Related

Connecting button programmatically XCode9, Objective-C, OSX

im on OSX, XCode9, Objective C.
I have a viewController layouted in IB. The view contains a button connected to the corresponding viewController
SHTourViewController.h
#property (weak) IBOutlet SHStandardButton *closeButton;
// SHStandardButton is a subclass from NSBUtton.
The view controller gets instantinated by code in another class (i need to instantinate this viewController from other classes cause i need it more than once).
// Get instance of viewController
SHTourViewController* tourViewController = [storyBoard instantiateControllerWithIdentifier:#"tourViewController"];
Now in viewDidLoad method of my viewController, i like to connect the buttons action and target:
SHTourViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.closeButton setAction:#selector(closeButtonClicked:)];
[self.closeButton setTarget:self];
}
- (void)closeButtonClicked:(id)sender {
NSLog(#"CLOSE!");
}
}
When i click the button, the app crashes (Thread 1: EXC_BAD_ACCESS). I can't find the mistake i am doing here.
Any help appreciated.
You are not supplying enough information about what you're doing. But, as it stands, the fact that fact that you are getting a Bad Access would suggest that some important object has vanished prematurely in a puff of smoke. My guess is that that object is self, and that the problem has to do with code after this line:
SHTourViewController* tourViewController =
[storyBoard instantiateControllerWithIdentifier:#"tourViewController"];
You are obtaining a completely new instance of this view controller but then you are not getting its view correctly into the view hierarchy and the view controller itself into the view controller hierarchy, so the view controller (I'm guessing) is released.
But you didn't show us the relevant code, so that's just a guess.

Return for a push segue

I am new to story boards and I am trying to move between table view controllers.
I understand how to set up a segue and how to send data to the new story board but my question is returning data back. If I use the push style segue it gives me an automatic back button. I want a page that will create a "job" and save it if they hit save (a bar button I created on the other side of the title) When I set up the segue to go back to the main page from the save button it made that main table view controller a child (instead of simply going back to it's original state). The work around I was thinking was saving it to a file when they hit save and whenever they load the main table view it loads from that file. Is this a common and correct way to do this or should I be trying to return that object and save it in the main table view controller?
A common approach is to use delegation. Since ViewControllers should be as independent as it is possible, we have to minimize dependencies between them. And actually your idea with the file, if I understand it correctly, does it as well. But using files to organize a communication between ViewControllers is not very convinient.
Usually you declare a #protocol SecondViewControllerDelegate for your second ViewController (where you click a "Save" button). With methods like:
#protocol YourSecondViewControllerDelegate <NSObject>
-(void)yourSecondViewControllerDidCancel:(YourSecondViewController*)controller; //if you have a cancel button
-(void)yourSecondViewControllerDidFinish:(YourSecondViewController*)controller yourDataToReturn:(SomeData*)data andSomeMoreData:(AnotherDataType*)data2;
#end
Then you add a property like this to your SecondViewController:
#property (nonatomic, assign) id<YourSecondViewControllerDelegate> delegate; //Do not retain it!
Then you adopt your protocol in your MainViewController.
#interface MainViewController()<YourSecondViewControllerDelegate> //you can do it in the private category to keep the class interface clear.
#end
#implementation
//don't forget to implement those methods here :)
#end
And when you trigger your segue from the MainViewController, you can set your MainViewController as a delegate for the SecondViewController:
SecondViewController *destinationController = [[SecondViewController alloc] init]; //Just for example.
destinationController.delegate = self;
//trigger a segue :)
When the user presses the Save button in the SecondViewController, you call the delegate's yourSecondViewControllerDidFinish:
[self.delegate yourSecondViewControllerDidFinish: self yourDataToReturn: someData andSomeMoreDate: someMoreData];
This way MainController's yourSecondViewControllerDidFinish method will be called. And you can pick someData and someMoreData up there.
You can get more details about it in this tutorial:
Apple's your second iOS app tutorial
If you're making a segue to go "back" to a controller, then that segue needs to be an unwind segue. An unwind segue goes back to the same instance of the controller that you came from originally. If you need to send data back to that controller, you can do it in prepareForSegue.

How do I access the view of a Window from interfacebuilder?

I'm trying to make interfaces for a cocoa app in xcode's interface builder. The view of one of the windows I made in Interface builder depends on data from another view, so it is necessary to message this view from the class which must pass it data. However I can't seem to find a way to get a reference for this view object from the owner of the nib file. Here is roughly the code I'm using:
controller = [[NSWindowController alloc] initWithWindowNibName:#"Somenibname"];
[[controller window] display];
theOtherView = [[[[controller window] contentView] subviews] objectAtIndex:1];
[theOtherView setObjectwhichneedstobemessaged:self];
[theOtherView sendAMessage:self];
The object that this code is in never receives the message. Initially I actually thought that the contentview was the view that appears in interface builder and tried to get a reference to it like this
theOtherView = [[[controller window] contentView]];
but that didn't work either. Thanks for reading.
It sounds like you may need a better understanding of how the View-Controller structures work with nib files and without more code/detail its difficult to know exactly what you are trying to do, but a quick way to solve your problem could be to use NSNotification's instead of trying to locate the other view and instigate a message send via call chain.
You can register to handle a notification from the receiving view and send the notification from the instigating view (and vice versa if you need it two ways).
Read up on IBOutlet and consider linking the views that you need directly from Interface Builder.
For example, your NSWindowController subclass might have:
#interface MyWindowController : NSWindowController
{
/* can also use more specific classes if you need them, e.g. NSButton if it's really an NSButton */
IBOutlet NSView* firstViewIWant;
IBOutlet NSView* secondViewIWant;
}
. . .
#end
Your implementation might have:
- (void)
windowDidLoad
{
[super windowDidLoad];
/* make sure the views were connected properly */
assert(nil != firstViewIWant);
assert(nil != secondViewIWant);
. . .
}
Then in Interface Builder, hook up these outlets from "File's Owner" to the exact views that you need them to be.

how to share a xib file with multiple objective c class

I am new in ios development, so i don't know this question is correct or not.
I want to create a uibutton from a separate uiview class in view based application template.
if anybody know ,please clear my question.
That's pretty easy to do. This code snippet should help;
NSArray* nibRollViews = [[NSBundle mainBundle] loadNibNamed:#"TiltData" owner:self options:nil];
myRollDataView = [nibRollViews lastObject]; // TODO, look it up by name, don't assume last
[myRollDataView setFrame:CGRectMake(rollDataViewFPO.frame.origin.x,
rollDataViewFPO.frame.origin.y,
myRollDataView.frame.size.width,
myRollDataView.frame.size.height)];
[self.view addSubview:myRollDataView];
[myRollDataView initWithType:RollType];
There are a few things to note. I have a rollDataViewFPO (FPO means "for position only") in my xib. I use the FPO frame for positioning the object I just loaded. This way I can position it my xib, not my code.
Also note that I call my own initWithType method. My TiltData objects can be used to show Roll or Pitch data, and I need to tell them what type they are.
Add a newFile ObjectiveC class make it as SubClass of UIView(assume name here: SubView).
if you doesn't want to use the view of UIViewController Class then just select the view in xib
of UiViewController and change the class name to SubView in inspector window.put the UIButton
in that view and do anything what you want.If you want Separate View then simply drag and
drop UIView from menu bar and connect that as an outlet to your ViewController Class and
change name of UIView class to SubView.

Design an NSView subclass in Interface Builder and then instantiate it?

So I have an NSTabView that I'm dynamically resizing and populating with NSView subclasses. I would like to design the pages in IB and then instantiate them and add them to the NSTabView. I got the programmatic adding of NSView subclasses down, but I'm not sure how to design them in IB and then instantiate them.
I think I got it. Let me know if this is not a good thing to do.
I made a new xib file, set its File's Owner to be an NSViewController and set its "view" to the custom view I designed in the xib.
Then you just need:
NSViewController *viewController = [[NSViewController alloc] initWithNibName:#"MyViewXib" bundle:nil];
NSView *myView = [viewController view];
#toastie had a really good answer. Mine is similar, but requires a bit more explanation.
Let's say you've already got a controller object and you don't want to instantiate a new controller object just to get at a view, and let's say that you're going to need multiple copies of this view (for example, you've designed a custom UITableViewCell in IB and you want to instantiate it again and again from your UITableViewController). Here's how you would do that:
Add a new IBOutlet to your existing class called "specialView" (or something like that). It may also be helpful to declare it as a (nonatomic, retain) property.
Create a new view xib called "SpecialView", and build the view however you like.
Set the File's Owner of the view to be your controller object.
Set the specialView outlet of File's Owner to be the new view.
Whenever you need a new copy of the view in your code, you can simply do the following.
(gratuitous text to get formatting working properly)
NSNib * viewNib = [[NSNib alloc] initWithNibNamed:#"SpecialView" bundle:nil];
[viewNib instantiateNibWithOwner:self topLevelObjects:nil];
[viewNib release];
NSView * myInstantiatedSpecialView = [[[self specialView] retain] autorelease];
[self setSpecialView:nil];
Yes, it's a bit more code than other ways, but I prefer this method simply because the view shows up in the designated IBOutlet. I retain and autorelease the view, because I like to reset the outlet to nil once I have the view, so it can be immediately ready to load a new copy of the view. I'll also point out that the code for this is even shorter on the iPhone, which requires one line to load the view, and not 3 (as it does on the Mac). That line is simply:
[[NSBundle mainBundle] loadNibNamed:#"SpecialView" owner:self options:nil];
HTH!