I am using Xcode 4.6.2 and have created a new Tabbed Application using apples template. I have placed a UIWebView on my First View Controller and loaded http://google.co.uk into it. On my Second View Controller I have created a button that, when pressed, will load http://google.co.uk/images into the Web View on the first controller. It is this bit I am stuck on, here is my code so far:
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UIWebView *mainWebView;
}
-(void)imagesURL;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"First", #"First");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
- (void)viewDidLoad
{
[mainWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.co.uk"]]];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)imagesURL {
[mainWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.co.uk/images"]]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "FirstViewController.h"
#interface SecondViewController : UIViewController {
}
- (IBAction)imagesButton:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Second", #"Second");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self;
}
- (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)imagesButton:(id)sender {
FirstViewController *view1 = [[FirstViewController alloc] init];
[view1 imagesURL];
}
#end
At the moment, when I press the Images button on the Second View Controller and switch back to the first, nothing happens at all. The webpage doesn't load. its like the Void isn't being called. What am I doing wrong?
The problem is in this line here FirstViewController *view1 = [[FirstViewController alloc] init]; - that is creating an entirely new copy of your view controller, which is not the one you started with in your first tab.
I think you would benefit from following some Objective C tutorials, or perhaps one of the iOS programming courses on iTunes U so that if something like this occurs again you have some more background.
There are many ways to do what you are trying to do, but one of the most straightforward is to have your second view controller talk to the tab view controller displaying it to get the first view controller. There should be reasonable documentation about how to do this in the iOS UITabViewController docs.
Related
I dont know why my UIScroll view doesn't work. I am just learning iOS development and when I covered UIScrollView, I had problems in scrolling.
I created a new project just to check the scroll, but I had no luck. I'm using the iOS 6.1 simulator with Xcode 4.6.2.
This is my .h file:
#import <UIKit/UIKit.h>
#interface CDViewController12 : UIViewController<UIScrollViewDelegate>{
IBOutlet UIScrollView *scroll;
}
#end
and my .m file
#import "CDViewController12.h"
#interface CDViewController12 ()
#end
#implementation CDViewController12
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[scroll setScrollEnabled:YES];
scroll.contentSize = CGSizeMake(250, 2000);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[scroll release];
[super dealloc];
}
#end
What am I doing wrong?
Try deactivating the auto layout property.
In the file inspector uncheck the box "Use AutoLayout"
hope this help!
Make sure the the size of the scroll view is not larger than the size of the parent view.
i get some problem by removing the Edit Button from the moreNavigationController.
I cant find the mistake, it must be a simple one.
I create some TabBarViewController connect it in the IB with my TabBarViewController.
Here is the Code:
TabBarViewController.h:
#import <UIKit/UIKit.h>
#interface TabBarViewController : UITabBarController <UINavigationControllerDelegate, UITabBarControllerDelegate>
#end
TabBarViewController.m:
#import "TabBarViewController.h"
#interface TabBarViewController ()
#end
#implementation TabBarViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.delegate = self;
[self.moreNavigationController.navigationBar setBarStyle:UIBarStyleBlackOpaque];
[self.moreNavigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbar.bg.png"] forBarMetrics:UIBarMetricsDefault];
[self.moreNavigationController.navigationBar.topItem setRightBarButtonItem:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The Edit Button is stil there :/
You need to set the navigationController delegate to your tabBarController. Add the following line in your viewDidLoad method of your TabBarViewController class
self.moreNavigationController.delegate = self;
use the delegate method of UINavigationController navigationController:willShowViewController:animated: to hide the barButtonItem
Use the following code
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
navigationController.navigationBar.topItem.rightBarButtonItem = Nil;
}
This should work, it worked for me.
There is a more pretty solution:
tabBarController.customizableViewControllers = [];
Prasad Devadiga Thanks man!
In my TabBarViewController.m
#import "TabBarViewController.h"
#interface TabBarViewController ()
#end
#implementation TabBarViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.moreNavigationController.delegate = self;
navigationController:willShowViewController:animated:YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
navigationController.navigationBar.topItem.rightBarButtonItem = Nil;
}
#end
In my TabBarViewController.h
I insert this codes
#import <UIKit/UIKit.h>
#interface TabBarViewController : UITabBarController <UINavigationControllerDelegate, UITabBarControllerDelegate>
#end
This is working on IOS7
After reading all of the above and converting it to Swift 3 I noticed that when one of the view controllers which was shown after selecting the More... tab was a navigationcontroller and had a rightBarButton item, that item was removed as well! Since that is not desired, I came up with the following solution:
//
// CustomizedTabBarController.swift
//
import UIKit
class CustomizedTabBarController: UITabBarController, UINavigationControllerDelegate {
var root : UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
root = self.moreNavigationController.topViewController
// Make sure the icons have the proper tint color
if let view = root?.view {
view.tintColor = UIColor.green
}
self.moreNavigationController.delegate = self
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
// Only hide the rightBarButtonItem when this is the morenavigationcontroller
if( viewController == root ){
navigationController.navigationBar.topItem?.rightBarButtonItem = nil
}
}
}
As an extra I also force the icons shown in the moreNavigationController to be green instead of the standard blue tintcolor since I was using green icons on the tabbar as well.
This worked for me
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
tabBarController.customizableViewControllers?.removeAll()
}
I am attempting to get a UIViewController (GUI built using storyboard), to show when a DetailDisclosureButton is touched/pressed. I made a very simple GUI, with just a single button on the screen. I gave it the Custom Class NFLGameDetailsController, and did nothing else on the storyboard.
I then created a class named NFLGameDetailsController that inherited from the class UIViewController.
This is the code generated by Xcode when inheriting from the UIViewController class:
#import "NFLGameDetailsController.h"
#interface NFLGameDetailsController ()
#end
#implementation NFLGameDetailsController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Finally, on my main controller I added #import "NFLGameDetailsController.h" to my header file, and implemented the method to show my UIViewController like this:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
NFLGameDetailsController *controller = [[NFLGameDetailsController alloc] init];
[[self navigationController] pushViewController:controller animated:YES];
}
This method is getting called and all seems fine, but when I do press an accessory detail disclosure button, I get a black screen:
Why is it that it is not showing the GUI I created using the storyboard? Thanks.
it`s because you are instantiating just a class , not a view
if you want to load another view from code you can do this way
first , assign Storyboard ID to your viewcontroller in Storyboard editor ( for example NFLGameDetailsController )
then
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
NFLGameDetailsController *controller = (NFLGameDetailsController *)[self.storyboard instantiateViewControllerWithIdentifier:#"NFLGameDetailsController"];
[[self navigationController] pushViewController:controller animated:YES];
}
but you could use storyboard editor to configure your tableview and its` cell to load another view without code
I have a storyboard with 3 view controllers: QuestionsTableViewController, QuestionViewController and AnswerViewController
For all intensive purposes, QuestionsTableViewController is basically my main menu. it has a selection of topics which when selected populate a question label in QuestionViewController which is then segued to.
The user enters his/her answer in a UITextField and hits a submit button causing a modal segue to the AnswerViewController which has a label that returns either a correct or incorrect message to the user based on a comparison of their answer to the coded correct answer. This final View Controller also has a button (back to menu) that when clicked should take the user back to the QuestionsTableViewController (i.e. my menu).
This last part (the returning to the menu) is where I am having problems.
I can dismiss the AnswerViewController multiple ways, but I cant figure out what I need to do to dismiss the QuestionViewController as part of this same button press.
I am including snipets of my QuestionViewController and AnswerViewController classes below.
QuestionViewController.m
#import "QuestionViewController.h"
#import "AnswerViewController.h"
#interface QuestionViewController ()
#end
#implementation QuestionViewController
#synthesize currentQuestionDisplay;
#synthesize userAnswerTextField;
#synthesize currentQuestion;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
AnswerViewController *avc = [segue destinationViewController];
[avc setCurrentQuestion:currentQuestion];
[avc setUserAnswer:[userAnswerTextField text]];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.currentQuestionDisplay setText:[currentQuestion question]];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[self setCurrentQuestionDisplay:nil];
[self setUserAnswerTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)dismissKeyboard:(id)sender {
[userAnswerTextField resignFirstResponder];
}
- (void)dimissThisVC
{
[self dismissViewControllerAnimated:YES completion:^(void){}];
}
#end
AnswerViewController.m
#import "AnswerViewController.h"
#import "QuestionViewController.h"
#interface AnswerViewController ()
#end
#implementation AnswerViewController
#synthesize displayCurrentAnswer;
#synthesize currentQuestion;
#synthesize userAnswer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if([userAnswer isEqualToString:currentQuestion.answer]) {
[self.displayCurrentAnswer setText:#"You are correct!"];
}
else {
[self.displayCurrentAnswer setText:#"You are wrong!"];
}
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[self setDisplayCurrentAnswer:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)dismissAnswerVC:(id)sender {
[[self presentingViewController]
dismissViewControllerAnimated:YES
completion:^(void){ }];
}
#end
When you dismiss the modal view, in the completion block have this code:
[self.navigationController popViewControllerAnimated:YES];
Or if you want to go to the top most controller:
[self.navigationController popToRootViewControllerAnimated:YES];
in an effort to complete this post for others who may reference it, i am reposting user523234's answer here:
In the prepareForSegue method, you missed this line:
avc.delegate = self;
hopefully this can help someone else who has fallen into the same hole that i was in.
I know this is just a fundamental question but still somewhere I am missing something, I am playing with passing data to a textView from another class. For this I have created two classes one with xib file (ViewController) and another without(secondVC).
What I am trying to do is that I have a textview in ViewController class and wanted to pass the data to this textView from secondVC. This is how I am doing.
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController
- (void)print;
#end
//secondVC.m
- (void)print{
NSString *printThis = #"This works";
ViewController *vc = [[ViewController alloc] init];
[vc.textView setText:printThis];
//vc.textView.text = printThis //Tried both
}
Any suggestions would be appreciated.
Thanks
you can do like this :
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
sec.viewController = self;
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController {
ViewController *viewController;
}
#property(nonatomic, retain)ViewController *viewController;
- (void)print;
#end
//secondVC.m
#synthesize viewController;
- (void)print{
NSString *printThis = #"This works";
self.viewController.textView.text = printThis ;
}
Try with protocol... if you want to send string from textView(child) to other ViewController(parent)
You need a delegate method that is fired from the SecondVC and handled in the first one (ViewController).
There are a few issues here:
You've got a ViewController creating a new secondVC and sending it a print message. That's okay, but the implementation of -print creates a different instance of ViewController and tries to set the text of it's textView property. That's clearly not what you want -- you should instead be sending the text back to the original instance of ViewController.
That second instance of ViewController very likely has its textView property set to nil since textView is an outlet, but you haven't loaded its view from the .xib.
It's really not nice for one view controller to mess with the views of another view controller. The secondVC should be giving the text to the original ViewController object, not trying to set the text of one of its views.
To facilitate communication from secondVC to ViewController, give secondVC a property to keep track of the original ViewController. The usual thing to do here is to define a delegate protocol for secondVC and implement that protocol in ViewController. When ViewController creates secondVC, it sets the delegate of secondVC to itself. That gives secondVC a pointer to its delegate (it shouldn't care whether its a ViewController or some other kind of object, as long as the delegate implements the right methods).
.h file:
#import <UIKit/UIKit.h>
#protocol StringDelegate <NSObject>
-(void)getArrayOfStrings:(NSMutableArray*)strArray;
#end
#interface WWSettings : UIViewController{
}
#property(nonatomic,assign)id<StringDelegate>delegate;
#end
.m file:
#import "WWSettings.h"
#implementation WWSettings
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)blablablaFunction{
[delegate getArrayOfStrings:yourArray];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
if you dont understand how it works .. ask ! i'll make my best to help you )
your secondVC
#import <UIKit/UIKit.h>
#import "WWSettings.h"
#interface secondVC : UIViewController<StringDelegate>{
WWSettings *obj;
}
#end
and .m file :
#import "secondVC.h"
#implementation secondVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)getArrayOfStrings:(NSMutableArray *)strArray{
// here you get your array !!! it's a delegate function made by you in child viewController;
}
- (void)viewDidLoad
{
obj = [[WWSettings alloc]init];
[obj setDelegate:self];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
first VC .h file :
#import <UIKit/UIKit.h>
#protocol textViewChildDelegate <NSObject>
-(void)getStrings:(NSString*)string;
#end
#interface textViewChild : UIViewController<UITextViewDelegate>{
UITextView *textView;
}
#property(nonatomic,assign)id<textViewChildDelegate>delegate;
#end
.m file:
#import "textViewChild.h"
#implementation textViewChild
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)myWorkingMethod{
// get string from textView
[delegate getStrings:textView.text];
}
- (void)viewDidLoad
{
textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 240, 320, 240)];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
Now go to secondVC .h:
#import <UIKit/UIKit.h>
#import "textViewChild.h"
#interface TextViewViewController : UIViewController<textViewChildDelegate>{
UITextView * myfirstTextView;
}
#end
and to .m file:
#import "TextViewViewController.h"
#implementation TextViewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)getStrings:(NSString *)string{
myfirstTextView.text = string; // finally we get string from child view controller
}
- (void)viewDidUnload
{
myfirstTextView = [[UITextView alloc]init];
[super viewDidUnload];
// Release any retained subviews of the main view.
}