Changing UITextView with if statement from IBAction - ios

I've been searching a lot but it seems like I just can't figure it out. I'm pretty new to iOS development and I apologize if I am doing things completely wrong.
Here is the situation.
I am trying to switch the content view of my DetailViewController via button that should send you to the next text view or the same view but with different text.
This is my header file.
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextView *rowContent;
#property int rowNumber;
#property (strong, nonatomic) NSString * rowName;
#property (strong, nonatomic) IBOutlet UIBarButtonItem *rightArrow;
#end
My tableViewController redirects me to my DetailViewContoller depending on which cell I've selected. Now in my DetailViewController I have another button that I want to switch to next text instead of me going back to the tableViewController and selecting a different cell.
//DetailViewController
//set the title of the view
self.title = rowName;
//set the UITextView basec on rowNumber
switch (rowNumber) {
case 0:
rowContent.text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"file" ofType:#"txt"] encoding:NSUTF8StringEncoding error:nil];
break;
case 1:
rowContent.text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"file1" ofType:#"txt"] encoding:NSUTF8StringEncoding error:nil];
break;
case 2:
rowContent.text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"file2" ofType:#"txt"] encoding:NSUTF8StringEncoding error:nil];
break;
case 3:
rowContent.text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"file3" ofType:#"txt"] encoding:NSUTF8StringEncoding error:nil];
break;
default:
break;
//TableViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//create and instance of our DetailViewController
DetailViewController * DVC = [[DetailViewController alloc]init];
//set the DVC to the destinationViewContoller
DVC = [segue destinationViewController];
//get the indexPath
NSIndexPath * path = [self.tableView indexPathForSelectedRow];
NSString * theList = [rowList objectAtIndex:path.row];
DVC.rowNumber = path.row;
DVC.rowName = theList;
}

Your question is a bit confusing. If you want to switch to the next case, from a button, just write rowNumber ++; in your button method, and then call the method where your switch statement is.

If I'm understanding the question correctly, it sounds like you're trying to do something similar to what I recently did in an app. That is, you have a table view in a navigation controller that goes to a detail view when you select a cell, and you want to then be able to navigate between different detail views without going back to the table view to select another cell.
I did this using a UIPageViewController. It is a bit complicated to implement but is a nice clean method to use. The way it works is when you tap on a cell, it goes to a view that contains a UIPageViewController which then loads the appropriate 'page' depending on which cell was tapped. The UIPageViewController handles moving back and forth between pages. You provide a model controller that acts as the UIPageViewController's data source. Its role is to return a detail view controller for a given index (page number). To get the UIPageViewController to load the appropriate data for each page, you feed it the same data you are using to populate your table view.
Say you have three cells in your table. You tap the middle one, and it loads the view with the UIPageViewController. When the cell is tapped and you're transitioning to the detail view, you tell it which cell was tapped. The UIPageViewController then uses this info to load the correct detail view. When the user wants to navigate between pages, the UIPageViewController simply loads the data for the next or previous page with the data that corresponds to that cell in the table view.
Note that UIPageViewController doesn't know or care about the table view, it is simply using the same source data (such as an array) that the table view uses to load its data.
Documentation here.

Related

Where and how to set protocol delegate when slide out menu implemented in navigation controller?

Imagine you have the following storyboard scheme:
Slide out menu UITableView and feed UITableView embedded in Nav controllers
You want to filter out your feed based on the content of the cell that is tapped in the slide out menu.
As you can see on the storyboard scheme I shared above, you want to do this dynamically using only one segue whose identifier is:
#"Filter_MenuItem"
You declared the following protocol in the slide out menu view controller:
// SlideOutMenuTableViewController.h
#import <UIKit/UIKit.h>
#import "SlideOutMenuItems.h"
#import "SlideOutMenuCellTableViewCell.h"
#protocol filterFeed <NSObject>
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData; //String to pass slideOut menu item string back to feed
#end
#interface SlideOutMenuTableViewController : UITableViewController
#property(nonatomic,assign)id<filterFeed> stringDelegate;
#end
And you implement the protocol method filterFeedFromSlideOutItemTapped:in your feed view controller:
#pragma mark - Filter feed based on slideout menu item tapped
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData
{
NSLog(#"filterFeedFromSlideOutItemTapped just started");
if (!(slideOutItemStringData == (nil)))
{//Pass self.feed.flames + filtering string ==> filtered flames
NSMutableArray* allFlames = [[NSMutableArray alloc] initWithArray:self.feed.flames];
NSString *flameRelationFilter = slideOutItemStringData;
NSPredicate* sortFlames = [NSPredicate predicateWithFormat:#"(kFlameRelation like %#)", flameRelationFilter];
NSArray* filteredFlames = [allFlames filteredArrayUsingPredicate:sortFlames];
NSLog(#"The filter flames are %#", filteredFlames);
NSMutableArray *mutableFilteredFlames = [filteredFlames mutableCopy];
self.filteredFeed.flames = mutableFilteredFlames;
[self.tableView reloadData];
}
}
You make sure to synthesize your delegate in the implementation of your slide out menu view controller: #synthesize stringDelegate;
And before you call your protocol method in the implementation of your slide out menu view controller:
[stringDelegate filterFeedFromSlideOutItemTapped:[self.slideOutMenuItems menuItemAtIndex:indexPath.row]];
you know that, first, you need to initialize your protocol delegate:
instanceOfSlideOutMenuTableViewController.stringDelegate=self;
Generally, you do that successfully in a "prepareForSegue" method. But this time it's more complicated since you implemented a slide out menu (you actually didn't reinvent the wheel, you picked your implementation here).
Where and how should you initialize your protocol delegate?
Since you use SWRevealViewController which adds other controllers as child controllers, you can directly access feed controller from menu using parentViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// get reveal controller
SWRevealViewController *revealController = (SWRevealViewController *)self.navigationController.parentViewController;
// get content controller
UINavigationController *feedNavController = (UINavigationController *)revealController.frontViewController;
// rename "FeedController" to whatever class you use for front controller
FeedController *feedController = (FeedController *)feedNavController.topViewController;
// get menu item
NSString *menuItem = [self.slideOutMenuItems menuItemAtIndex:indexPath.row];
// pass selected item to feed controller
[feedController filterFeedFromSlideOutItemTapped:menuItem];
}
as i seen your storyboard you used SWRevealViewController to add the slider in your main bundle . you added a tableview to show the list of menu . so use "tableviewdidSelect" method to add your view controller to SwWRevealMain view that added your main view on the main Screen.

How to show multiple web view links on Xcode under one UIViewController

Suppose I have an app with 3 buttons each opening 3 different UIWebView view controllers. Instead of having 3 separate view controllers for each button, I want to have 1 UIWebView view controllers and depending on the button that is pressed, that is what will show on the UIWebView.
This is just an example of what I am talking about
firstViewController
Button 1 opens Yahoo
Button 2 opens Google
Button 3 opens Bing
secondViewController
if button1 is pressed, show Yahoo on the UIWebView
if button2 is pressed, show google on the UIWebView
if button3 is pressed, show bing o the UIWebView
How do I come up with this?
in iOS each object contains own tags if you are interest use tags else other options.
assume that your button1.tag=10, button2.tag=20 and button3.tag=30
set the global string for in .h file
NSString *activecheck;
// assign the single method for all buttons in touchup inside method
- (IBAction)button_GetDeals:(UIButton*)sender {
switch (sender.tag)
{
case 10:
activecheck=#"1";
break;
case 20:
activecheck=#"2";
break;
case 30:
activecheck=#"3";
break;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"secondviewcontrolleridentidiername"]) {
secondViewController *destViewController = segue.destinationViewController;
destViewController. buttontype = activecheck;
}
// this is your second view controller
#interface secondViewController : UIViewController
#property (nonatomic, strong) NSString *buttontype;
#property (strong, nonatomic) IBOutlet UIWebView *webview;
#end
in your .m file viewdidload
- (void)viewDidLoad
{
[super viewDidLoad];
if ([buttontype isEqualtoString:#"1"])
NSString *strURL = #"http://www.google.com";
NSURL *url = [NSURL URLWithString:strURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.webiew loadRequest:urlRequest];
}
just like follow the another two condition for bing and yahoo ....
Button 1 opens Yahoo
In its action
write:
[webView loadRequest:YOUR REQUEST_YAHOO];
// reload your view
Button 2 opens Google
In its action
write:
[webView loadRequest:YOUR REQUEST_GOOGLE];
// reload your view
Button 3 opens Bing
In its action
write:
[webView loadRequest:YOUR REQUEST_Bing];
// reload your view
For reload your view you can use:
[self.view setNeedsDisplay]; //such methods

Using the same view controller multiple times

I'm new to Objective-C and have a question. Did the search multiple times but I couldn't find what I was looking for.
I'm using storyboard for this app. On the homescreen you've got some buttons with labels above them. Those labels should tell a number. When pushing the button you go to a new viewController where you have input that (after 'save') goes back to the homescreen and updates the label with the correct number. All that works great for one button and I'm very happy about it.
The problems are:
1. Since I have multiple buttons with labels, I want to use the same viewController to give input over and over again. I tried connecting every button to slide to the viewController under the identifier "AddData", but Xcode doesn't allow the same identifiers twice or more in storyboard. So I would need something else for this. Any idea?
2. Currently I use the following code to bring back the data to the homescreen:
homeScreenViewController
- (IBAction)unwindToHomeScreen:(UIStoryboardSegue *)segue;
{
inputDataViewController *source = [segue sourceViewController];
self.logoOneLabel.text = source.endTotalNumber;
}
inputDataViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton) {
return;
} else {
if (endTotalLabelNumber > 0) {
self.endTotalNumber = [NSString stringWithFormat:#"%.0f", totalLabelNumber + endTotalLabelNumber];
} else if (endTotalLabelNumber == 0 && totalLabelNumber == 0){
self.endTotalNumber = 0;
} else {
self.endTotalNumber = [NSString stringWithFormat:#"%.0f", totalLabelNumber + endTotalLabelNumber];
}
}
}
This works great for the one button, but how to use this with multiple? I heard about Delegates to use the same viewController multiple time and get data back to different places, but I just don't get it. Any help?
You shouldn't need delegates.
What you will need is a property on the view controller that handles input to it knows which button it is handling input for.
When you segue to the input controller, set this property, based on which button was pushed. When you unwind back, fetch this property to know which label to modify.
For example, in your input view controller's .h file, add a property like this:
#property (nonatomic,assign) NSInteger handlingTag;
Or something, whatever name makes sense to you.
Now you need to implement your home screen view controller's prepareForSegue:sender:.
Use the sender argument to determine which button was pushed, and based on that, set the input view controller's new handlingTag property based on the button in a way that you will know what to do with it when we unwind.
Now in the unwind method:
switch (source.handlingTag)
Create a switch structure based on the source's handlingTag property, and set the appropriate label based on this value.
As Jeff points out in the comments, it'd be a really good idea to define an NS_ENUM to use here for the property rather than an NSInteger. The NS_ENUM would allow you to name the values you're using.
There is a few different way to implement what you need. But i think most common its a delegate.
This is how your inputDataViewController looks like:
#import <UIKit/UIKit.h>
#protocol inputDataDelegate;
#interface inputDataViewController : UIViewController
#property (weak) id<inputDataDelegate> delegate;
#property (strong, nonatomic) NSNumber *buttonTag;
#end
#protocol inputDataDelegate <NSObject>
-(void) inputDataViewControllerDismissed:(id)data;
#end
Then in #implementation, you should in "save" button action, message to you delegate method :
[self inputDataViewControllerDismissed:#{#"buttonTag":buttonTag,#"endTotalNumber":endTotalNumber}
Next in homeScreenViewController connect delegate :
#interface homeScreenViewController : UIViewController<inputDataDelegate>
After that in #implementation:
-(void)inputDataViewControllerDismissed:(id)data
{
// if you use modal
[self dismissViewControllerAnimated:YES completion:nil];
// or if you use push
//[self.navigationController popViewControllerAnimated:YES];
switch (data[#"buttonTag"]) {
case 1:
self.lableWtiTagOne = data[#"endTotalNumber"];
break;
case 2:
self.lableWtiTagTwo = data[#"endTotalNumber"];
break;
// number of cases depend how many buttons you have
}
Also, most important, thing didn't forget send self to our delegate:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"inputDataController"])
{
inputDataViewController *inputCtrl = [segue destinationViewController];
inputCtrl.delegate = self;
inputCtrl.buttonTag = sender.tag
}
}

How to Update Label From Different View Controller using NSUserDefaults

I am trying to update a label on view controller 1 by pressing a button on different view controller 2. I have this IBAction in the view controller 2:
- (IBAction)done:(id)sender {
DropPinVC * vc = [[DropPinVC alloc]init];
NSString *updatedLabel = [[NSUserDefaults standardUserDefaults] stringForKey:#"Type Location"];
NSLog(#"Updated Label = %#", updatedLabel);
vc.TypeLabel.text = updatedLabel;
[self closeScreen];
}
However, the label on view controller 1 does not update. Does anybody know a solution to this problem?
vc is a new instance of DropPinVC class declared in the scope of the action posted, and is not the same instance as the one you want to update.
One way to achieve this is to keep a pointer to the first view controller.
In order for viewController2(vc2) to update a UILabel that is owned by viewController1(vc1), vc2 needs a reference to vc1 so it can access the label.
Add a property to vc2 of type DropPinVC
#property (nonatomic, strong) DropPinVC *vc1Ref;
Assuming vc1 allocates and initialises vc2 then where after this happens assign the vc1Ref property.
vc2.vc1Ref = self;
Now in the IBAction, your code can now access the correct instance and update the correct label.
- (IBAction)done:(id)sender {
NSString *updatedLabel = [[NSUserDefaults standardUserDefaults] stringForKey:#"Type Location"];
NSLog(#"Updated Label = %#", updatedLabel);
self.vc1Ref.TypeLabel.text = updatedLabel;
[self closeScreen];
}

How do I use If-Statements correctly?

I tried a few things myself, but couldnt really get the handle around it.
I wanna do two things:
First the user can press one of three buttons - They all link to the same ViewController, but when User Presses the first button three labels change accordingly in this second ViewController. And then the user can enter some data which will be displayed in the third view, also accordingly on which button was pressed in the first view.
I tried it with IF Statements, e.g. (IF ViewController.button1waspressed == True) and it didnt really work. I also tried it with tags e.g. (Button1.tag = 1)
Could someone give me a short example on how this could work?
FirstViewController.m
- (IBAction)switch:(id)sender;
{
SecondViewController *second =[[SecondViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
SecondViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
if (sender == self.button1) {
NSString *greeting = [[NSString alloc] initWithFormat:#"Randomtext"];
self.label.text = greeting;
}
}
The problem is obvious in this one, SecondViewController cant see the property from the first one. (And yes I imported the FirstViewController and vice versa)
Your buttons should all directly call IBActions (methods defined like so):
- (IBAction)doSomething:(id)sender;
Defining them as IBActions exposes them to be connected with the blue connection lines in interface builder. Once you've hooked them up and the method is being called, you can simply use an equality check on the sender parameter, which the calling button will automatically set as itself.
if (sender == self.myButton) {
// do something
}
Here I'm assuming that you've got a property called myButton in your ViewController, which would be an IBOutlet:
#property (nonatomic, retain) IBoutlet UIButton *myButton;
This exposes that property to be connected with the blue connection lines in interface builder, so your ViewController will know exactly which button you're talking about when you say myButton.

Resources