Program looking for method in wrong location - ios

I am working on a split view controller app, i have two views, a detail view and a second view. When a value on my first view is selected. (say we select dog). my second view loads a few options on the left pane. Therefore from that left pane when i select Color. I want my uilabel to read."Dog is Black" or if I had selected cat from the first view, i want it to read Cat is yellow. when i select color.
So what i did is, in the didSelectRowAtIndexPath i have
if ([[animalArray objectAtIndex:indexPath.row]isEqualToString:#"dog"] )
{
secondView *detailList=[[secondView alloc]init];
[self.detailViewController.navigationController pushViewController:detailList animated:YES];
self.activeOption=#"dog";
//defined as #property (nonatomic, assign) NSString *activeOption; in .h file
}
Then in my secondView i have ( tried to extract the most important things
.h file
#property (nonatomic,retain) DetailViewController *detailViewController;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
if ([self. detailViewController.activeOption isEqualToString:#"dog"]) {
self.labelOne.text=#"The Dog is Black";
}
}
Now my problem is, when i click the row to load the second view (dog) i get this error.-[secondView activeOption]: unrecognized selector sent to instance .
Now i believe you get that when you call a method that doesn't exist, so while the method does exist, it doesn't exist in secondView but in the DetailView So i am at a lost as too why it is looking there for the method. even if i said self.detailviewController.
Thanks

Related

IOS/Objective-C: Change object behind detail view of tableview programmatically

In a master tableview-detail view controller app, after loading a detail view, I would like to let the user view the detail for a different item from the tableview if they wish.
To do this, I pass two objects to the detail view in prepareForSegue and use one of them to load the view.
If I want, I am able to change individual items on the screen one by one, for example, by changing self.title = item.title to self.title = altitem.title. My question, is, whether there is a way to reload the entire view using the alternative object?
I have read that setNeedsDisplay should reload the whole view, but it is not changing the object behind the view or at least the view on the screen Here is my code currently:
//in prepareForSegue method in master tableview
destViewController.item=item;;
destViewController.altItem=altitem;
//in .h file of detail view
#property (nonatomic, strong) Items *item;
#property (nonatomic, strong) Items *altitem;
// in .m file of detailView
in viewDidLoad
self.title = item.title;
//my method to change object - NOT DOING ANYTING
-(void) reloadWithAltItem {
self.item = self.altitem;
[self.view setNeedsDisplay];
}
Thanks for any suggestions.

setting properties in the detail view from prepareForSegue

I created a Master/Detail application with xCode and changed very little about it. In prepareForSegue in the MasterViewController, I added this to try to put some text in a label in the detail view controller
MMDetailViewController *detailVC = [segue destinationViewController];
detailVC.testdetail.text = #"test";
I also added a label to the detailViewController on the storyboard and then did control/drag to the detailViewController to connect them.
#property (strong, nonatomic) IBOutlet UILabel *testdetail;
Therefore, when I set the text in prepareForSegue, I expected it to show in the label once I ran the code on the simulator. However, it didn't show. Can you explain why?
Its because you can't update the UILabel before it load...
So what you need to do is this:
Make Nsstring and update it value, then in viewDidLoad update your Label.
In your detailViewController.h add
#property (strong, nonatomic)NSString *testString;
Then in the detailViewController.m in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.testdetail.text = testString;
}
in your masterViewController:
MMDetailViewController *detailVC = [segue destinationViewController];
detailVC.testString = #"test";
That's it, it should work now :)
Happy coding
The outlets are accessible after -viewDidLoad is fired. That didn't happen yet in -prepareForSegue:, so you probably access a label with nil value.
Ensure that detailVC.testdetail is not nil in -prepareForSegue: first.
If it's nil, which I assume, the UILabel isn't loaded yet. See IBOutlet properties does not update when using prepareForSegue method
Instead, use a NSString property to pass the value around. Put the value into the label in -viewDidLoad of your destination MMDetailViewController because it's responsible for doing that itself.

How get data from View to UITabBarController

I have a UITabBarController, which has 3 UIViewControllers. Each controller has a few UITextFields. In UItabBarController is a button "save". Please, how can I get data from UITextFields in UIViewControllores? I need the data from all UITextFields and from all UIViewControllers in UITabBarController (in IBAction of save button). How can I do it? Thanks.
Here is picture of my TabBarController on Storyboard.
The first ViewController has a class StudentVC. The class has one text field. In StudentVC.m is this code:
#import <UIKit/UIKit.h>
#import "CoreDataHelper.h"
#interface StudentVC : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) NSManagedObjectID *selectedStudentID;
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
#property (strong, nonatomic) IBOutlet UITextField *studentNameTextField;
#end
The studentNameTextField is connected with field in Storyboard. Then I have a class for TabBar the class name is StudentTBC. In file StudentTBC.m I have this code:
- (void)viewDidLoad
{
if (debug == 1) {
NSLog(#"Running %# '%#'", self.class, NSStringFromSelector(_cmd));
}
[super viewDidLoad];
StudentVC *studentVC = [self.tabBarController.viewControllers objectAtIndex:0];
studentVC.studentNameTextField.text = #"asad";
}
So, when I go on TabBar I will see in studentNameTextField the text "asad", but the field is clear... So I added also in IBAction:save this code:
- (IBAction)save:(id)sender {
if (debug == 1) {
NSLog(#"Running %# '%#'", self.class, NSStringFromSelector(_cmd));
}
StudentVC *studentVC = [self.tabBarController.viewControllers objectAtIndex:0];
NSString *string = studentVC.studentNameTextField.text;
NSLog(#"string:%#", string);
But when I insert the field and press "ulozit" (its save in czech), I get a "string: null" instead of a "string: textWhichIWriteToField". I tried indexes 0,1,2 but nothing works. :/
Edited 3.4 15:20
I did a move of my application. In first part is my storyboard - UITabBarController and 3UIViewControllers. I deleted a Navagition Controllers. In second part I do again a Outlets. Third part is code of save function (the code could be write a content of textfield) and code of ViewDidLoad of TabBarController (code could be set a string of textfield). The last part is run application (the result is in console - null string and clear textfield).
I also tried print this:
NSInteger countOfViews = [self.tabBarController.viewControllers count];
NSLog(#"count:%ld", (long)countOfViews);
It has to be three? or? Because my result was 0.. Why? :/
My movie: https://www.youtube.com/watch?v=j6p__e48lLI&feature=youtu.be
EDITED 2.4 20:58 -------------------
Hello. I tried all options but nothing worked.. So I did a new SIMPLE application, where is only one UITabBarController with two UIViewControllers and one UITableViewController (because of navigation bar). Please download the project and try it yourself. Only run, then click on button "TabBar" and you are on the UITabBarController. When you press a Save button, it should display a count of UIViewsControllers and the value of textfields. Could you please try and tell me what's wrong? Thank you. Here is the project:
https://www.dropbox.com/s/r4jlzadr2us00ad/TBC.zip
To access to one of text field you can use code below:
- (IBAction)save {
YourUIViewController *vc = [self.tabBarController.viewControllers objectAtIndex:indexOfController];
NSString *str = vc.yourTextField.text;
}
EDIT. You have me how your controllers are connected and now i realized you got UINavigaitonController after UIViewController. Modified code should look like:
- (IBAction)save {
NSArray *navConArr = [self.tabBarController.viewControllers objectAtIndex:indexOfController];
for(UINavigationController *nc in nacConArr) {
UIViewController *vc = [nc.viewControllers objectAtIndex:0];
NSLog(#"And your text is = %#", vc.studentNameTextField.text);
}
}
Updated
I solved the problem finally... The right code for TabBarController
- (IBAction)save {
YourUIViewController *vc = [self.viewControllers objectAtIndex:indexOfController];
NSString *str = vc.yourTextField.text;
}
Please check outlets for UITextFields,
Also check output for
NSLog(#"StudentVC textField -- %#",studentVC.studentNameTextField); in save()
if it is also null, then there is definitely problem with your outlets.

ViewController not accepting value from other ViewController

I'm working on a program in whirlyglobe.
When the program starts it animates to a part of the map from this code in the view did load
[globeViewC animateToPosition:MaplyCoordinateMakeWithDegrees(-122.4192, 37.7793) time:1.0];
This works fine however I am trying to get the map to animate as well when I select a cell in my masterView controller so I have this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[[[TypesArray objectAtIndex:indexPath.row]objectForKey:#"regions"]objectForKey:#"region"]isEqualToString:#"Caribbean"])
{
TestViewController *testView=[[TestViewController alloc]init];
// Start up over San Francisco
[testView.globeViewC animateToPosition:MaplyCoordinateMakeWithDegrees(-122.4192, 37.7793) time:1.0];
NSLog(#"test");
}
"Test" shows in the log but it doesn't animate to the spot on the map.
I have added #import "TestViewController.h" to the top of this file and
#property(nonatomic,
strong) WhirlyGlobeViewController *globeViewC;
was added to TestViewController.h
#import <UIKit/UIKit.h>
#import "WhirlyGlobeComponent.h"
#import "ConfigViewController.h"
// Map or globe or startup
typedef enum {MaplyGlobe,MaplyGlobeWithElevation,Maply3DMap,Maply2DMap,MaplyNumTypes} MapType;
//The Test View Controller brings up the WhirlyGlobe Component
// and allows the user to test various functionality.
#interface TestViewController : UIViewController <WhirlyGlobeViewControllerDelegate,MaplyViewControllerDelegate,UIPopoverControllerDelegate>
{
/// This is the base class shared between the MaplyViewController and the WhirlyGlobeViewController
MaplyBaseViewController *baseViewC;
/// If we're displaying a globe, this is set
WhirlyGlobeViewController *globeViewC;
/// If we're displaying a map, this is set
MaplyViewController *mapViewC;
UIPopoverController *popControl;
}
// Fire it up with a particular base layer and map or globe display
- (id)initWithMapType:(MapType)mapType;
#property(nonatomic,strong) NSString *parse;
#property(nonatomic,strong) WhirlyGlobeViewController *globeViewC;
#property(nonatomic,strong) MaplyViewController *mapViewC;
#end
I believe you have things a bit mixed up...
Let’s suppose your masterviewcontroller is your car, your testvc is the axle and your WhirlyGlobeViewController are the wheels.
What you are doing right now is : i’m pushing a button in my car that does not have neither axle nor wheels, so i order a axle and i expect the (non existing) wheels to roll. That just don’t make any sense. You have to attach your axle to your car and get the wheels and attach them to your axle.
Your whirlyglobe is attached (initialized) in viewdidload (i guess) in testviewcontroller, but that method is never called.
You are saying that the line in testviewcontroller works, that’s because (i guess) you are using your testviewcontroller independently and viewdidload is called automatically.
From here you have two options. The first one is where your globe is available is all your program, and then it should probably be a property or an instance variable of MasterViewController
instead of TestViewController. Then you could copy the code in your testviewcontroller’s viewdidload method to your masterviewviewcontroller’s viewdidload method. (the part where whirly globe is initialized)
Then you would have to call your animation by doing
[globeViewC animateToPosition:MaplyCoordinateMakeWithDegrees(-122.4192, 37.7793) time:1.0];
NSLog(#"test");
The other option is that testviewcontroller should be independant and only the globe should be in here. Then you should probably display somewhere that controller by using pushViewController or adding a childviewcontroller, for instance :
TestViewController *testView=[[TestViewController alloc]init];
//If you have a navigation view controller
[self.navigationController pushViewController: testView animated:YES];
//If you don't
[self addChildViewController:testView]; // testView's viewDidLoad will be called here
[self.view addSubview:testView.view];
NSLog(#"test");
Try this
TestViewController *testView= [[TestViewController alloc] initWithNibName:#"Page1" bundle:nil];
OR
TestViewController *testView = [self.storyboard instantiateViewControllerWithIdentifier:#"viewControllrID"];

Modifying UIButton's alpha property from another class

I'm trying to change the alpha of an UIButton from another class. The function that is called in set the alpha property of my UIButton is actually called because I've put a NSLog there and I can see how it works. I'd be thankful if you could give me any suggestion.
Here's my current code.
ViewController.h
- (void) setAlphaToButton;
#property (strong, nonatomic) IBOutlet UIButton *myButton;
ViewController.m
#synthesize myButton;
- (void) setAlphaToButton {
myButton.alpha = 0.5;
NSLog(#"Alpha set");
}
ImageViewSubclass.m
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
ViewController *VC = [[ViewController alloc] init];
[VC setAlphaToButton];
}
And when the image view is pressed, in my console I get: Alpha set. And the button doesn't change.
In your code, an instance of ViewController is alloced and inited, and the method setAlphaToButton is called on it. Then the view controller is released because you have no object retaining it. That's why you don't see any effect; the ViewController instance you call the method on never appears on screen.
It's not clear how your code is supposed to work; do you have an instance of ViewController in existence when tapDetected is called? If this is the case, and this is the ViewController whose button you want to alter the alpha of, then you need to have a reference to that instance of ViewController and call setAlphaToButton on it.
Your view is not loaded at the moment you trying to set alpha! You need to call this method after your viewDidLoad fired. You can force it by calling view, but it's kind of hackand not recommended!
MyViewController *vc = [MyViewController new];
vc.view; // this string will force view loading
[vc setAlphaToButton];
Add a property of uiviewcontroller class in imageviewsubclass as
ImageViewSubclass.h
#propery (nonatomic, retain) uiviewController *parent;
ImageViewSubclass.m
#synthesize parent;
And initialize it with "self" in view controller class when initalize object of imageviewsubclass and add on the view like
ImageViewsubclass *oneObj = [ImageViewsubClass alloc] init];
oneOBj.parent = self;
do the same for all objects of ImageviewsubClass objects.
and in
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
[parent setAlphaToButton];
}

Resources