Why NSInteger cannot set from parent view controller? - ios

In my childview controller I have this property:
#property (nonatomic, assign) NSInteger currentItemIndex;
In parent view controller, I want to set that value.
[childViewController setCurrentItemIndex:5];
[self.navigationController pushViewController:childViewController animated:YES];
But in the childViewController, currentItemIndex is 0.
Why I cannot set it? Where am I wrong?

ReceiverViewController.h
#property (nonatomic, assign) NSInteger currrentIndex;
ReceiverViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"Index value %d",self.currrentIndex);
}
DataPassingViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
DataPassingViewController *detailViewController = [[DataPassingViewController alloc] initWithNibName:#"DataPassingViewController" bundle:nil];
detailViewController.currrentIndex = 5;
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
I used the above code which gives a output as follows:
2013-07-10 17:50:10.230 DataPassing[3881:c07] Index value 5

Try to read _CurrentIndex inside your childview class, this variable should be autogenerated and set using the setter setItemIndex method.
I had too an experience with Xcode that when i did a build for 64 bit target, the internal variable with underscore was generated automatically, but for 32 bit target i had to declare it in interface and use the #synthesize statement in inplementation to get the code to compile.

Just declare simply, as
#property NSInteger currentItemIndex;
And if it dont solve the problem, you have to tell where you declare the property, which class, in interface declaration or not, which xcode you are using etc. post more code.
e.g. for xcode 4.6 this is okay. but for old xcode you have synthesize the property.

Related

Update property used in a tableView from another viewController

I have FirstViewController and SecondTableViewController. In SecondTableViewController.m, I create a cell in the cellForRow... method where the cell.textLabel.text is a string from an NSInteger property ("count") of the SecondTableViewController.
I would like a button in FirstViewController to increment the value of count.
I've tried making a property of FirstViewController and then using that:
#property SecondTableViewController *viewController;
and
- (IBAction)buttonTouched:(id)sender {
self.viewController.count++;
[self.viewController.tableView reloadData];
}
But this way isn't working. count is still its original value of zero. I've also reloaded the table in viewWillAppear and still nothing. How can I do this?
Count being used as a property may be where you are going wrong because count is a method that returns the number of objects in an array that is found in foundation framework. Also keep in mind that if you are storing a integer into a string object try storing it in this format.
cell.textlabel.text = [NSString stringWithFormat: #"%i", count];
Hope this helps
Try following
firstViewController.h
#interface DMFirstViewController : UIViewController
#property (nonatomic, strong) DMSecondViewController * secondController;
- (IBAction)buttonPressed:(id)sender;
#end
firstViewController.m
- (IBAction)buttonPressed:(id)sender
{
++self.secondController.count;
[self.navigationController pushViewController:self.secondController animated:YES];
}
secondViewController.h
#property (nonatomic) int count;
secondViewController.m
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%d", self.count);
}
EDIT
Check out those two images and implement the similar logic and get the solution.
----- END OF NEW EDIT -----
OLD
I think you haven't assigned and allocated memory for SecondTableViewController reference i.e, self.viewController of FirstViewController in its viewDidLoad method i.e,
-(void) viewDidLoad //In FirstViewController
{
self.viewController = [[SecondTableViewController alloc] init];
}
and pushed the same reference on to the stack of navigationController after performing button taps to increase the count of count variable of SecondTableViewController.
If you are not clear, comment.

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.

passing data value between two view controller using custom protocol

1) I Am passing the value between two view controller using custom
protocol..But the value always showing NULL.
I need to pass the value from second view controller to first view controller
2) In Secondview controller.h
#protocol PopoverTableViewControllerDelegate <NSObject>
#property (nonatomic, strong) id<PopoverTableViewControllerDelegate>myDelegate;
3) secondview controller.m
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary*dict=[sercharray objectAtIndex:index];
str=[dict objectForKey:#"id"];
NSLog(#"test value %#",str);
[self.myDelegate didSelectRow:str];
NSLog(#"delegate value %#",self.myDelegate);
//THIS VALUE ALWAYS SHOWING NULL AND ALSO I SHOULD PASS THIS VALUE TO FIRST VIEW
CONTROLLER.I SHOULD USE DISMISS VIEW CONTROLLER.
[self dismissViewControllerAnimated:YES completion:nil];
}
4) First View controller.h
#interface Firstviewcontroller :
UIViewController<PopoverTableViewControllerDelegate>
5) First view controller.m
secondviewcontroller *next=[[seconviewcontroller alloc]init];
next.myDelegate=self;
(void)didSelectRow:(NSString *)cellDataString {
passstring = cellDataString;
NSLog(#"pass string %#",pass string);
//first view controller str variable value i need to pass this string[passstring].
}
I think you might be a little confused about what Delegation is used for and why. For example you might want to make a protocol in a UIViewController subclass if you were doing some kind of action in that ViewController and needed to inform another subclass that that action is being taken, or of the result of that action. Now in order for the subclass that wants to know about the action(the receiver), it has to conform to that protocol in it's header file. You also must "set" the delegate to the receiving class/controller. There are many ways to get a reference to the receiving controller/class to set it as the delegate but a common mistake is allocating and initializing a new instance of that class to set it as the delegate, when that class has already been created.What that does is set your newly created class as the delegate instead of the class that's already been created and waiting for a message. What your trying to do is just pass a value to a Newly created class. Since your just creating this UIViewController class all thats needed for that is a Property in the receiver(ViewControllerTwo). In your case a NSString:
#Property (nonatiomic, retain) NSString *string; //goes in ViewControllerTwo.h
and of course don't forget in the main:
#synthesize string; //Goes in ViewControllerTwo.m
Now there is no need for a setter in your ViewControllerTwo.
- (void)setString:(NSString *)str //This Method can be erased
{ //The setter is created for free
self.myString = str; // when you synthesized the property
}
The setter and Getters are free when you use the #synthesize. Just Pass the value over to the ViewController. The implementation is identical to your code except for the delegate:
ViewControllerTwo *two = [[ViewControllerTwo alloc] initWithNibName:#"ViewControllerTwo" bundle:nil];
[two setString:theString];
[self.navigationController pushViewController:two animated:YES];
[two release];

xctest - how to test if a new view loads on a button press

Just started xcode 5 and xctest. How do I test that a view loads on button press. I have programatically added method that gets called when the rightBarButtonItem is clicked
action:#selector(onSettingsButton)
and in onSettingsButton
-(void) onSettingsButton{
SettingsViewController *svc = [[SettingsViewController alloc] init];
[self.navigationController pushViewController:svc animated:YES];
}
How to write xctest to ensure SettingsViewController brings up the Settings view? Thank you.
You need an interaction test — that is, a test that checks interactions between objects. In this case, you want to test that -pushViewController:animated: is called on the navigation controller with a SettingsViewController. So we want to put a mock object into self.navigationController which we can ask, "Were you called as expected?"
I'll assume a simple name for the class: MyView.
The way I'd do this by hand is to Subclass and Override navigationController. So in my test code, I'd do something like this:
#interface TestableMyView : MyView
#property (nonatomic, strong) id mockNavigationController;
#end
#implementation TestableMyView
- (UINavigationController *)navigationController
{
return mockNavigationController;
}
#end
Now instead of creating a MyView, the test will create a TestableMyView and set its mockNavigationController property.
This mock can be anything, as long as it responds to -pushViewController:animated: and records the arguments. Here's a simple example, by hand:
#interface MockNavigationController : NSObject
#property (nonatomic) int pushViewControllerCount;
#property (nonatomic, strong) UIViewController *pushedViewController;
#property (nonatomic) BOOL wasPushViewControllerAnimated;
#end
#implementation MockNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
self.pushViewControllerCount += 1;
self.pushedViewController = viewController;
self.wasPushViewControllerAnimated = animated;
}
#end
Finally, here's a test:
- (void)testOnSettingsButton_ShouldPushSettingsViewController
{
// given
MockNavigationController *mockNav = [[MockNavigationController alloc] init];
TestableMyView *sut = [[TestableMyView alloc] init];
sut.mockNavigationController = mockNav;
// when
[sut onSettingsButton];
// then
XCTAssertEquals(1, mockNav.pushViewControllerCount);
XCTAssertTrue([mockNav.pushedViewController isKindOfClass:[SettingsViewController class]]);
}
These things can be simplified by using mock object frameworks such as OCMock, OCMockito, or Kiwi's mocking. But I think it helps to start by hand first, so that you understand the concepts. Then choose the tools that help. And if you know how to do it by hand, you'll never say, "Mocking framework X doesn't do what I need! I'm stuck!"
Found one way. Maybe there are others ..
- (void)testSettingsViewShowsWhenSettingsButtonIsClicked{
[self.tipViewController onSettingsButton];
id temp = self.tipViewController.navigationController.visibleViewController;
XCTAssertEqual([temp class], [SettingsViewController class], #"Current controller should be Settings view controller");
}
First call the onSettingsButton, which is the same as clicking the button, but not really. Maybe it's okay for this simple test case? How to simulate the actual press?
Then get the current view from the tipviewcontoller which is the rootview of the app and check that it is a SettingsViewController.

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