I'm new to iOS and Objective-C. I have an application that displays a table view, and opens a new view when click the user clicks on a row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[detailController changeSubjectText:[subject_data_Array objectAtIndex:indexPath.row]];
//navigationController = [[UINavigationController alloc] initWithRootViewController:detailController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
}
In my detail view I have coded:
-(IBAction)closeDetail:(id)sender {
NSLog(#"closeDetail");
[self.view removeFromSuperview];
}
But it's not working. Can anyone help?
Can anyone help me?
how i can close view?
download my code in --> http://www.vasuta.com/ios/multiview2.zip
open build and run click one row in "Bulletin Board" DetailView it's open click Close …..
why DetailView is not full screen and why can't close detail view?
i open it wrong or i close it wrong
help me please
didSelectRowAtIndexPath you can see in "GadgetBulletinsTVContoller.m" and close command you can see in "DetailViewController.m"
Thank you very much
ps. sorry for my english skill :(
Why are you creating that window object and why are you trying to add your subview to it?
if you want to add a subview you should add it to the parent, the tableview or the parent of the tableView.
a better idea would be to push a new view controller on the stack that would display the info you want to show.
Here is a tutorial that shows how to push a new view controller when selecting a cell in a tableview tutorial link .
EDIT:
in MultipleAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions should look like below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MultipleViewController alloc] initWithNibName:#"MultipleViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
In GadgetBulletinsTVContoller.h declare a protocol like below:
#protocol GadgetBulletinsTVControllerDelegate <NSObject>
#optional
- (void)showItemDetails:(id)selectedItem;
#end
and a delegate property:
#property (nonatomic, assign)id<GadgetBulletinsTVControllerDelegate>delegate;
In GadgetBulletinsTVContoller.m synthesize the delegate.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
should look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if([delegate respondsToSelector:#selector(showItemDetails:)])
{
[delegate showItemDetails:[subject_data_Array objectAtIndex:indexPath.row]];
}
}
In FirstViewController.m tell the controller to implement the GadgetBulletinsTVControllerDelegate like this:
#interface FirstViewController ()<GadgetBulletinsTVControllerDelegate>
in viewDidLoad method tell the gadgetBulletinsController that his delegate is the FirstViewController class, like this:
if (gadgetBulletinsContoller == nil) {
gadgetBulletinsContoller = [[GadgetBulletinsTVContoller alloc] init];
gadgetBulletinsContoller.delegate = self;
}
and implement the GadgetBulletinsTVControllerDelegate's methods:
- (void)showItemDetails:(id)selectedItem
{
if([delegate respondsToSelector:#selector(showDetailsScreenForItem:)])
{
[delegate showDetailsScreenForItem:selectedItem];
}
}
In FirstViewController.h declare a protocol like below:
#protocol FirstViewControllerDelegate <NSObject>
- (void)showDetailsScreenForItem:(id)item;
#end
and declare a delegate property like below(don't forget to synthesize in .m file):
#property (nonatomic, assign)IBOutlet id<FirstViewControllerDelegate>delegate;
In MultipleViewController.xib select the FirstViewController screen and in outlets drag from the delegate to the fileOwner for setting the value of the delegate to the MultipleViewController(you can do this in code if you want to).
In MultipleViewController.m tell the MultipleViewController to implement the FirstViewControllerDelegate protocol like below:
#interface MultipleViewController ()<FirstViewControllerDelegate>
and implement the protocol method:
- (void)showDetailsScreenForItem:(id)item
{
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[detailController changeSubjectText:item];
[self.navigationController pushViewController:detailController animated:YES];
}
In DetailViewController modify the closeDetail method to look like this:
- (IBAction)closeDetail:(id)sender {
NSLog(#"closeDetail");
[self.navigationController popViewControllerAnimated:YES];
}
and voila, Your GadgetBulletinsTVController items details are pushed. You need to do the same steps for the other controllers from where you want to show details.
instead of removing the view from window just reload the basic view which contains all the table views using self.window.rootviewcontroller
EDIT
i got the solution by creating appDelegate what you have to do is just described below
First .h and .m file of AppDelegate Here (MultipleAppDelegate)
in .h add
#property (strong, nonatomic) id<UIApplicationDelegate>delegate;
in .m add
#synthesize delegate;
now where ever you like to add detailView just add below in .h and .m files as described
in .h file here(GadgetBulletinsTVContoller)
#import "MultipleAppDelegate.h"
and in interface one variable like this
MultipleAppDelegate *Mydelegate;
in .m file in viewDidLoad or loadView method
Mydelegate = [[UIApplication sharedApplication]delegate];
then at loading the detailView do this
navigationController = [[UINavigationController alloc] initWithRootViewController:detailController];
Mydelegate.window.rootViewController = navigationController;
[Mydelegate.window makeKeyAndVisible];
now at the detailViewController's .h and .m files
in .h file
#import "MultipleAppDelegate.h"
and in interface
MultipleAppDelegate *appDelegate;
in .m file in viewDidLoad or loadView method
appDelegate = [[UIApplication sharedApplication]delegate];
and on close button click
//Not required
//[self.navigationController popViewControllerAnimated:NO];
appDelegate.viewController = [[MultipleViewController alloc] initWithNibName:#"MultipleViewController" bundle:nil];
appDelegate.window.rootViewController = appDelegate.viewController;
[appDelegate.window makeKeyAndVisible];
That's all it will work fine only problem is that it take's 1 or 2 seconds to navigate and show the multipalViewController
enjoy Coding :)
Happy Coding :)
Related
Anybody know how to implement search template like in Apple tvOS Human Interface Guidelines, using native development in Objective-C or Swift, without TVML ?
So, after research I was able to find a solution:
Objective - C
If in application is tabBar, i created a subclass from UITabBarController e.g. APTabBarController. In APTabBarController, in method
- (void)viewDidLoad
I do next:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SearchResultsViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:#"SearchResultsViewController"];
UISearchController *searchController = [[UISearchController alloc] initWithViewController:myViewController];
UISearchContainerViewController *containerVC = [[UISearchContainerViewController alloc] initWithSearchController: searchController];
containerVC.title = #"Search";
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: containerVC];
NSMutableArray *newTab = [self.viewControllers mutableCopy];
[newTab addObject: navigationController];
[self setViewControllers: newTab];
Where:
storyboard - is my storyboard
SearchResultsViewController - is my controller from storyboard that contains collectionView
UISearchController - is controller that allow to find what do you need
UISearchContainerViewController - and these one is like a view controller from tabBarController
In "newTab" - I add fresh created viewController that i need
But, problem that I found is that i can't catch searched text. For that, create a subclass from UISearchController, and implement custom
initWithViewController
In my case it looks like these:
In .h
#import <UIKit/UIKit.h>
#interface SearchExercisesViewController : UISearchController
- (id) initWithViewController:(UIViewController *) viewController;
#end
In .m
#import "SearchExercisesViewController.h"
#interface SearchExercisesViewController () <UISearchBarDelegate>
#property (nonatomic, strong) UIViewController *viewController;
#end
#implementation SearchExercisesViewController
- (id) initWithViewController:(UIViewController *) viewController {
self = [super initWithSearchResultsController:viewController];
if (self) {
self.viewController = viewController;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.searchBar.delegate = self;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"%#",searchText);
}
#end
Profit, and now, replace
UISearchController *searchController = [[UISearchController alloc] initWithViewController:myViewController];
with
SearchExercisesViewController *searchController = [[SearchExercisesViewController alloc] initWithViewController:myViewController];
All done. Now only that remain is to sent data to viewController that contains collection view, and implement logic for search. For sent data you can you Delegate pattern or NSNotification. You can find how to implement that in that post:
it possible to Pass Data with popViewControllerAnimated?
Swift
In swift is the same, how to do that, you can find on Apple example from these link:
https://github.com/brunogb/TVExamples/tree/master/UIKitCatalogtvOSCreatingandCustomizingUIKitControls
Sounds like you want to look at UISearchController.
I'm trying to make a button take me to a new UIViewController based on the content of a textField, but when I run it and hit the button (with the right condition in the text field to take me to the new UIViewController), the screen blacks out. This is what I wrote in my .h and .m files. Can anyone help me (Im using storyboards)
#interface ViewController : UIViewController
- (IBAction)boton:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *texto;
#end
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize texto;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)boton:(id)sender {
if ([texto.text isEqualToString:#"1"]) {
ViewController2 *vc1=[[ViewController2 alloc]init];
[self presentViewController:vc1 animated:YES completion:nil];
}
}
#end
As you say the screen is blacking out, I expect your viewController is getting initialised without a view.
To initialise with a view hierarchy from a xib(nib) file:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
where nibName can be nil if it shares it's name with the View Controller, and nibBundle can be nil it the nib is in the main bundle.
i.e....
ViewController2 *vc2;
vc2 = [[ViewController2 alloc] initWithNibName:nil
bundle:nil];
where the xib file is named ViewController2.xib
To initialise from a storyboard:
UIStoryboard *storyboard = self.storyboard;
vc2 = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
(you need to set up a viewController in storyboard and give it a matching identifier)
To initialise with neither storyboard or xib, you should override your view controller's - (void)loadView, create a view and assign it to self.view.
Update
In answer to your comment - the UIStoryboard... and ViewController2 *vc2= ... code would go into your button code (in your case it you would replace / adapt the line containing vc1=.... It would look like this:
- (IBAction)boton:(id)sender {
if ([texto.text isEqualToString:#"1"]) {
ViewController2 *vc2;
UIStoryboard *storyboard = self.storyboard;
vc2 = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
[self presentViewController:vc2 animated:YES completion:nil];
}
You will need to have created a storyboard scene in your storyboard with a viewController whose custom class is ViewController2 and identifier is "ViewController2". The identifier name is arbitrary, but must match the identifier string you use in your code.
As you are using storyboards, an alternative way to do this is to create a modal segue from the 'ViewController' scene to a 'ViewController2' scene, give it an identifier, and use performSegueWithIdentifier in your button method.
I'm trying to replace my current viewController with a new one. I've been able to do this before but I'm having some issues with BAD_ACCESS.
This is the code that will run when I want to replace the current view with a new one.
(The function will be called using a local property "self.some_data" (nonatomic, retain))
-(void) labelSelected:(SomeDataObject*) some_data{
SomeViewController *viewController = (SomeViewController*)[[ClassManager sharedInstance] viewControllerForClassIdentifier:#"com.somename" fromPlistFileName:#"iPhoneScreenList"];
viewController.data = (NSObject*)some_data;
[some_data retain];
//[self.navigationController pushViewController:viewController animated:YES];
UINavigationController *tempNavigationController = self.navigationController;
[[self retain] autorelease];
[tempNavigationController popViewControllerAnimated:FALSE];
[tempNavigationController pushViewController:viewController animated:TRUE];
}
Here everything works fine. The issue is that if I release the new "viewController" it crashes. And if I choose:
[tempNavigationController popViewControllerAnimated:TRUE];
I get some really wierd behaviour where the controller never gets replace and I return to the rootController and the navigation bar has two layers of text on it.
And if I do this:
[tempNavigationController pushViewController:viewController animated:FALSE];
I get BAD_ACCESS and the application chrashes. It worked before but not anymore.
What am I doing wrong?
Thanks!
Use category for controller replace:
// UINavigationController+ReplaceStack.h
#interface UINavigationController (ReplaceStack)
- (void) replaceLastWith:(UIViewController *) controller;
#end
// UINavigationController+ReplaceStack.m
#import "UINavigationController+ReplaceStack.h"
#implementation UINavigationController (ReplaceStack)
- (void) replaceLastWith:(UIViewController *) controller {
NSMutableArray *stackViewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
[stackViewControllers removeLastObject];
[stackViewControllers addObject:controller];
[self setViewControllers:stackViewControllers animated:YES];
}
#end
I am trying to call a subview after a button is clicked on my root controller. The warnings appear in my AppDelegate (code is below), but I included the method from my root controller on how I call this new subview also in case that too has a problem.
the alerts that continue to come up are that the local declaration of navController hides an instance variable.
When I launch the application (which used to open fine) it now simply exits out...
#import "SEM2REDOAppDelegate.h"
#import "SEM2REDOViewController.h"
#implementation SEM2REDOAppDelegate
#synthesize window;
#synthesize navController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window makeKeyAndVisible];
SEM2REDOViewController *firstController = [[SEM2REDOViewController alloc]
initWithNibName:#"SEM2REDOViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
[self setNavContorller:navController];
[window addSubview:[navController view]];
[navController release];
[firstController release];
return YES;
}
then here is the method inside of my first view controller
- (IBAction)chooseFirstMeeting:(id)sender {
SelectRotationController *selectView = [[SelectRotationController alloc]
initWithNibName:#"SelectView" bundle:[NSBundle mainBundle]];
[selectView.navigationItem setTitle:#"Select First Meeting"];
[self.navigationController pushViewController:self.selectRotationController animated:YES];
self.selectRotationController = selectView;
[selectView release];
}
I know this may be an extremely simple question but I've just started this. doing an intensive study on programming in high school as an added course so I'd really appreciate any help!
Rename navController
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
into something else. You can do this automatically by control-clicking word "navController", choosing "Refactor" from context menu, and then "Rename...".
Explanation:
The problem, I believe, in your local variable navController having the same name as instance variable under synthesized declared property navController.
Edit:
Also, this seems to be a typo:
[self setNavContorller:navController];
Correct:
[self setNavController:navController];
I just created an empty iOS project and added a UIViewController with a nib file. This should load my main view.
How do I tell my application to load a certain UIViewController as main view? Do I have to set it on the app delegate or somewhere in xcode?
In your app delegate have a variable for the controller....
MyViewController myController;
Then you want...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myController = [[MYViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.window addSubview:myController.view];
[self.window makeKeyAndVisible];
return YES;
}
You can also hook this up via Interface Builder, but the above is how you would do it in code.