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"];
Related
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
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.
I am struggling to make a simple thing (at least I think it's simple) but I just can't do it!
I will try to explain a little bit.
It's an app which displays information. When the user is inside a view, he can click on a button, which displays a popoverview, where he can choose which information he wants to know.
Actually, I can't create an action that changes the UILabel text I created in the main view when the user clicks on the popoverview's buttons.
Anyone has any idea?
Just for you to know: the main view I created a class for it, and also for the popoverview. Although, the popover view I created its design in a XIB file (I don't know if this is important, that's why I am putting this).
Well, I hope you guys were able to understand my question.
Thanks in advance.
Fernando.
Just create a property from the viewcontroller and access it from the consumer (other viewcontroller )
You will have to use delegation in order to see changes in the main view when you are making different actions inside the popover. First, you need to create a protocol inside your popover controller header file:
#import <Foundation/Foundation.h>
#class MyPopoverController;
#protocol MyPopoverDelegate
- (void)valueChanged:(NSString*) newVal;
#end
#interface MyPopoverController: UIPopoverController
#property (weak) id<MyPopoverDelegate> delegate;
#end
Then in .m you implement it like this:
- (void) someActionOccured
{
if([self.delegate respondsToSelector:#selector(valueChanged:)]){
[self.delegate valueChanged:valueYouWantToSendBack];
}
}
Remember that in your main class you have to implement MyPopoverDelegate protocol:
#interface MainViewController: UIViewController <MyPopoverDelegate>
And when you instantiate your popover controller:
/*
** inside MainViewController.m
*/
// remember to assign it's delegate
MyPopoverController *popoverController = [MyPopoverController alloc] init];
popoverController.delegate = self;
Also, you'll have to implement the protocol's method:
/*
** inside MainViewController.m
*/
- (void)valueChanged:(NSString*) newVal
{
// process the string and display it where you need it
}
ok, this may be a very basic question and I apologise if it is, but its driving me mad and I really need to get a better understanding.
I have an app that I am developing and using a new view controller and xib file for each page.
I call each page by using this code:-
HelpVC = [[[HelpViewController alloc] initWithNibName:#"HelpViewController" bundle: [NSBundle mainBundle]]autorelease];
[self presentModalViewController:HelpVC animated:YES];
Which works great.
However if I have this declared in a file and I then want to call it somewhere else I am getting errors all over the place.
is there any way to initialise all the xib files first in a class file and then call them from that file when needed??
Thanks
This is the error I get back
error: expected specifier-qualifier-list before 'UserInputViewController'
It seems to cause all of my declarations in the .h file to error with the message above.
Some sample code is:-
.h file
#import <UIKit/UIKit.h>
#import "CgePWViewController.h"
#import "LogBackInViewController.h"
#import "LoginViewController.h"
#interface SettingsViewController : UIViewController
{
CgePWViewController *cPWVC;
LogBackInViewController *LBIVC;
LoginViewController *login;
}
#property(nonatomic, retain) CgePWViewController *cPWVC;
#property(nonatomic, retain) LogBackInViewController *LBIVC;
#property(nonatomic, retain) LoginViewController *login;
so basically as soon as I have added in LoginViewController it causes everything else to error, if I take this out then the app runs perfectly.
Does your LoginViewController.h imports the SettingsViewController as well? It seems to be a "cross reference" (I don't know if this term makes sense in English as it does in Portuguese).
Before your
#interface SettingsViewController : UIViewController
put a
#class LoginViewController;
and check if it helps.
Don't initialise your view controllers to put them in properties. Instead, create them as soon as you need them.
Let's assume you want to show a view controller when somebody pushes a button. Add this method to your view controller (let's assume it's named MyFirstViewController):
- (IBAction)someButtonDidPush: (UIButton *)sender {
MySecondViewController *vc = [[MySecondViewController alloc] init];
// Do stuff and then show it. One way may be like this:
[self presentViewController: vc animated: YES completion: nil];
}
Just hook up the button with the method above. No properties needed! You're (probably) done.
When I start my iPad app, I want to display a screen that slides in on top of the main view that is there at the start up. I want this screen to take up the entire screen and display a web page, and the only way that the user can get out of it is click on a UIButton at the bottom of the screen.
Right now, I am setting the view of my main view controller as the view that I want to display, but the next step in execution is showing a UIAlert, and this alert is appearing.
What can I use to have this pop up wait for the user to click Agree before continuing?
Thanks.
You will want to use a delegate.
So to do what you want do something like this (I don't know your actual class names, so I'm guessing):
In your AlertScreenViewController.h file add this code:
#protocol AlertScreenViewControllerDelegate;
#interface AlertScreenViewController : UIViewController {
...
id<AlertScreenViewControllerDelegate> delegate;
...
}
...
#property (assign) id<AlertScreenViewControllerDelegate> delegate;
...
#end
#protocol AlertScreenViewControllerDelegate <NSObject>
- (void)alertScreenViewControllerWillClose;
#end
Then in your AlertScreenViewController.m file:
add this:
#implementation AlertScreenViewController
...
#synthesize delegate;
...
#end
add this code wherever your button is pressed:
[self.delegate alertScreenViewControllerWillClose];
In your MainViewController.h file add this:
#import "AlertScreenViewController.h"
#interface MainViewController : UIViewController <AlertScreenViewControllerDelegate> {
...
}
...
#end
In your MainViewController.m file add this:
Wherever you've loaded up the AlertScreenViewController add this after the init call:
alertscreenviewcontroller.delegate = self;
Then move all code after the display of the alertscreenviewcontroller code to this method:
- (void) alertScreenViewControllerWillClose {
//UIAlert logic here
}
You can find another example here: http://www.dosomethinghere.com/2009/07/18/setting-up-a-delegate-in-the-iphone-sdk/
Or just google iphone sdk delegate