I'm new to Xcode and therefor i'm to build small apps. i've recently got a problem, i just cant seem to find.
i've made a send button, that is going to send me from ViewController2 to ViewController.
Viewcontroller2.h
#interface ViewController2 : UIViewController {
ViewController *viewController;
}
- (IBAction)SaveData:(id)sender;
ViewController.m
- (IBAction)SaveData:(id)sender {
viewController = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self.view addSubview: viewController.view];
}
i've checked every connection in storyboard is correct, but i still get this error.
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I'm not 100% sure on what exactly is causing the error. As discussed in comments, segues are a much easier way of dealing with transitions between view controllers, so unless you have a particularly good reason to not use segues, I'd start learning segues (since you're learning new stuff anyway).
The error, however, is probably related to this:
[self.view addSubview: viewController.view];
When you do this, what you seem to be trying to do is taking the view (visual part) and adding it to the view of ViewController2. Meanwhile, ViewController2 doesn't have any controls set up for that view, and you wrote a lot of code in viewController that is pointless because you're never actually instantiating a view with that controller.
The above line I posted should be replaced with the following if you're not going to use segues:
[self presentViewController:viewController animated:YES completion:nil];
And this should be called after setting the properties on viewController for the data you wish to pass.
Better, however, is to just use storyboard segues. No matter how you call your segue, you're going to pass data by overriding the prepareForSegue:sender: method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"segueNameHere"]) {
ViewController* viewController = [segue destinationViewController];
// now set the properties of viewController
}
}
Related
After a viewcontroller has been presented modally, the initial preferredfocusedview is called. However, after we dismiss the viewcontroller and it has been dealloc. preferredfocusedview is not called after presenting the viewcontroller again. Running on tvOS 9.2.
Even adding the following did not help:
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self setNeedsFocusUpdate];
[self updateFocusIfNeeded];
}
Anyone know what's going on? Or if there's anyways to debug this?
Edit:
the way I am adding the viewcontroller:
viewController = [[UIViewController alloc] init];
[viewController addChildViewController:self];
[viewController.view addSubview:self.view];
[self didMoveToParentViewController:viewController];
If you are using a container view, having multiple ViewControllers or adding only one View Controller, the preferredFocusEnvironments method must be called from the rootView Controller indicating which View Controller to focus.
For eg.
View Controller A has a container View having ViewControllers B and ViewController C inside the Container.
View Controller A should have preferredFocusEnvironments returning which ViewController to focus.
This way, preferredFocusEnvironments on ViewController B or ViewController C will be called whenever the view becomes visible.
If the ViewController A doesn't have preferredFocusEnvironments, then it won't be called on the containerView ViewControllers.
Implementing custom focus behavior in tvOS 9 is disaster. Apple already mentioned that there is a limitation on redirecting focus specially when presenting/ dismissing a viewcontroller in WWDC.
tvOS10 will handle munch better with preferredFocusEnvironments.
https://developer.apple.com/videos/play/wwdc2016/215/
When I needed to fix this focus redirection issues in viewDidAppear in tvOS 9, I had exactly same issues. Sometimes it works, sometimes not. No clue what so ever. But after I put split second delay on setNeedsFocusUpdate / updateFocusIfNeeded in viewDidAppear it was way better in terms of consistency. preferredFocusedView get called all the time.
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setNeedsFocusUpdate];
[self updateFocusIfNeeded];
});
}
Do this in both presented and presenting view controllers, if you are manually changing focus. This is all from my observation and I don't think there is a proper way to achieve some focus behavior because tvOS API is kind of new and premature. Sorry about not being able to give you good explanation why this might work. Good luck.
hey guys created a custom segue tab bar, using this guys tutorial,
http://www.scott-sherwood.com/tutorial/ios-5-creating-a-custom-side-tabbar-using-storyboards-and-custom-segues/
after trying to figure out why why my app doesn't work, i realised that the technique i was using was about replacing the existing view with the linked ViewController as a subview.
////////////////////////////////////////// the over-written perform method as follows /////////////////////////
-(void) perform {
ViewController *src = (ViewController *)[self sourceViewController];
UIViewController *dst = (UIViewController *) self.destinationViewController;
for (UIView *view in src.placeholderView.subviews ) {
[view removeFromSuperview];
}
src.currentViewController = dst;
[src.placeholderView addSubview:dst.view]; }
////////////////////////////////////////////// /////////////////////// /////////////////////// ///////////////////////
now once i am on the linked ViewControllers i was hoping to add another link to another ViewController which would hold the Editing functions for the information each respective pervious ViewControllers. Now when i try to connect a the ViewControllers via any Segue the app crashes and give me a Thread 1:EXC_BAD_ACCESS. When i use NSZombie its give me this in the console,
[UIStoryboardSegueTemplate performSelector:withObject:withObject:]: message sent to deallocated instance 0x7c3a4d20
no i understand what is happening in theory, the viewController is trying to ad the next one to an empty space (i think the entire placeHolder has been deleted thus giving the viewController nowhere to go) i think, i was wondering if anyone could help with this i mean i a have been looking everywhere for a solution but i keep getting the same error.
i even created a VieController class for the ProfileViewController.m/ProfileViewController.h in which i add
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"ProfileEditSegue"]){
ProfileViewController *cvc = (ProfileViewController *)[segue destinationViewController];
[cvc.placeholderView addSubview:cvc.view];
}
}
this to leads me to the same errors. I will be glad to send anyone my source files, the same error occurs when i do it on the supplied files from the tutorial.
PS. i am using this method so that i can have a vertical navigation bar, but i want to do it simply so i could also learn how one works and be able to use/develope it further.
any help would be great
The problem wasnt in those methods it was because the currentViewController instances was set to weak instead of strong
I am setting up an iPad app that uses a SplitViewController. In my app delegate I have the following in didFinishLaunchingWithOptions:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *leftNavController = [splitViewController.viewControllers objectAtIndex:0];
LeftViewController *leftViewController = (LeftViewController*)[leftNavController topViewController];
DetailViewController *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
NSLog(#"Detail View Ctrl >> %#", [detailViewController class]);
When I run the app, the NSLog statement returns "UINavigationController" when DetailViewController is actually a subclass of UIViewController. However, in XCode, code completion shows all the methods that are implemented in the DetailViewController subclass. Any ideas? Thanks!
I think your DetailViewController is actually embedded inside a UINavigationController, and your fourth line is in error. Take a look instead at the topViewController for the second view controller inside your split view controller, much like you do for the LeftViewController.
The reason Xcode is continuing to suggest completion for DetailViewController methods is because you've given it that type. Code completion doesn't rely on runtime behavior (how could it?) – instead, it relies on static analysis of the code that you type. If you tell Xcode that something is a DetailViewController, it'll believe you and autocomplete based on that information.
I am very new to iPhone app development.
I am developing one example application for iPhone emulator using Objective-C++ and std CPP.
I have two views in my application, on some events from CPP code i am displaying second view using following code from the first view controller.
// Defined in .h file
secondViewScreenController *mSecondViewScreen;
// .mm file Code gets called based on event from CPP (common interface function between Objective-C++ and CPP code)
mSecondViewScreen = [[secondViewScreenController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:mSecondViewScreen animated:YES];
I am able to see second view coming on screen, but problem is that i am unable to end/remove second view controller from first view controller.
How can i remove second view controller from first view controller using second view controller's pointer or using any other method.
To remove second view i have following code in second view controller file, which gets called on button click event of second view.
// In .mm of second view controller.
- (IBAction)onEndBtnClicked:(UIButton *)sender
{
[self dismissModalViewControllerAnimated:NO];
[self.navigationController popViewControllerAnimated:YES];
}
Above code works perfectly, when i click on the seconds view's end button it removes the second view controller from the screen and navigets to first view, how can i use same code to remove second view from the first view controller.
I tied to use NSNotificationCenter to send event from first view to second view to call the function onEndBtnClicked but it is not working.
What is the proper way of doing it?
OSX version: 10.5.8 and Xcode version: 3.1.3
In the secondViewController create a protocol like:
#protocol SecondViewScreenControllerDelegate <NSObject>
- (void)secondViewScreenControllerDidPressCancelButton:(UIViewController *)viewController sender:(id)sender;
// Any other button possibilities
#end
Now you have to add a property in the secondViewController class:
#property (weak, nonatomic) id<SecondViewScreenControllerDelegate> delegate;
You sinthesize it in the secondViewController implementation:
#synthesize delegate = _delegate;
Finally all you have to do is implement the protocol in your firstViewController and set the secondViewController properly prior presenting it:
#interface firstViewController : UIViewController <SecondViewScreenControllerDelegate>
...
#implementation firstViewController
- (void)secondViewScreenControllerDidPressCancelButton:(UIViewController *)viewController sender:(id)sender
{
// Do something with the sender if needed
[viewController dismissViewControllerAnimated:YES completion:NULL];
}
Then when presenting the secondViewController from the first:
UIViewController *sec = [[SecondViewController alloc] init]; // If you don't need any nib don't call the method, use init instead
sec.delegate = self;
[self presentViewController:sec animated:YES completion:NULL];
And ready. Whenever you want to dismiss the secondViewController from the first, just call: (inside the secondViewController implementation)
[self.delegate secondViewScreenControllerDidPressCancelButton:self sender:nil]; // Use nil or any other object to send as a sender
All that happens is that you send a pointer of the secondViewController that you can use from the first. Then you can work with it without problem. No C++ needed. In Cocoa you won't need C++. Almost everything can be done with Objective-C, and it's more dynamic.
If there are only two views in your application then use
- (IBAction)onEndBtnClicked:(UIButton *)sender
{
[self dismissModalViewControllerAnimated:NO];
}
remove line below:
[self.navigationController popViewControllerAnimated:YES];
as it is you are dismissing second view then why you want to remove it from first view.
...
SecondViewController *svc = [SecondViewController new];
[self presentViewController:svc animated:YES completion:NULL];
}
This code is exactly the same as what I used in another app, but here I'm using presentViewController rather than presentModalViewController
(completion:NULL makes them effectively identical. Same result, at least.)
Both attempts at creating a modal view are structured the same way. Those lines in the main view, a view controller in the Storyboard, and matching .h and .m files. The only difference is that here I want a programmatic trigger, so it's impossible to drag a segue and be done with it.
I have an object set to recognize a gesture and call the transition method. That's probably what's causing the problem (part of it, at least), but it is necessary.
Using a UIButton would be cheating. No deadline, no shortcuts.
EDIT: NSLog output shows something odd.
2012-04-05 10:41:12.047 MyApp[5962:707] <SecondViewController: 0x1d8c130>
2012-04-05 10:41:12.479 MyApp[5962:707] <SecondViewController: 0x1d8e360>
So I'm doing something stupid again that happens to have a very simple fix, right?
Edit again: presentViewController… was being called more than once. Fixed it. Still black, though.
Back to performSegueWithIdentifier:sender: instead of the much easier presentViewController:animated:completion:
Terminating app due to uncaught exception 'NSInvalidArgumentException", reason: 'Receiver … has no segue with identifier …'
I told it to perform a segue, but there isn't one in the Storyboard (I can't add one, there is no Storyboard Segues section under 'Connections inspector' for the object I'm attempting to use), so it crashes. This is normal behavior.
What I want is to have a modal view without needing to create a segue. I've done it, so I know it's possible.
All I need is a bit of help getting it to work.
.
performSegueWithIdentifier:#"Identifier" sender:nil NSSInvalidArgumentException
presentViewController:viewController animated:YES completion:NULL Empty View
Got it.
Replace the lines in the question with this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard"
bundle:nil];
SecondViewController *viewController =
[storyboard instantiateViewControllerWithIdentifier:#"SecondView"];
[self presentViewController:svc animated:YES completion:NULL];
Credit for this solution goes to IturPablo's self-answered question:
TabBarController, overwriting shouldSelectViewController to do a segue
Are you looking for performSegueWithIdentifier:sender:? The docs seem to match your description:
"you can call this method to trigger a segue programmatically, perhaps
in response to some action that cannot be specified in the storyboard
resource file"