Push from an SKScene to a view controller - uiviewcontroller

I'm trying to do the following:
SKTransition *reveal = [SKTransition pushWithDirection:SKTransitionDirectionDown duration:0.5];
SKView *skv = (SKView *)self.view.window.rootViewController.view;
[self.view presentScene:skv.scene transition:reveal];
but it doesn't work, I get a SIGABRT Error. What can I use to get the same effect. I can use dismissViewController but then how do I use the pushWithDirection effect.

I'm not entirely sure why you want to push to the view controller. If you just want to transition to a new scene you can do this from within the scene, without going near the parent view controller:
YourScene *nextScene = [[YourScene alloc] initWithSize:self.size];
SKTransition *reveal = [SKTransition pushWithDirection:SKTransitionDirectionDown duration:3.0];
[self.view presentScene:nextScene transition:reveal];
If you do want to call this from the view controller you can add the view controller as a property in your scene:
#import "YourViewController.h"
#property (nonatomic,weak) YourViewController *viewController;
In your view controller when you set up your initial scene, assign the view controller to that attribute:
yourScene.viewController = self;
Then, from within the scene you can call methods on the view controller:
[viewController yourMethod];
which is:
//YourViewController.h
#import "YourScene.h"
...
-(void)yourMethod;
//YourViewController.m
...
-(void)yourMethod
{
YourScene *nextScene = [[YourScene alloc] initWithSize:self.size];
nextScene.viewController = self;
SKTransition *reveal = [SKTransition pushWithDirection:SKTransitionDirectionDown duration:3.0];
[yourSKView presentScene:nextScene transition:doors ];
}

Related

How to present a View Controller from the Detail View Controller correctly?

I have a UISplitViewController which presents a UIViewController with the following code:
self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
UIViewController *quiz = [[UIViewController alloc] initWithNibName:nil bundle:nil];
[self showDetailViewController:quiz sender:self];
I want to be able to present more view controllers from the already presented detail view controller that has been presented with -showDetailViewController. Do I simply call -presentViewController:animated:completion: or am I able to replace the current detail view controller with the view controller I would like to present?
The problem that I am have is that my quiz vc has a button with the following code that brings the user back to the UISplitViewController. When I use this code from the vc that the quiz vc presented with -presentViewController:animated:completion: nothing happens, but if this code is executed directly from the quiz vc it takes the user back to the main split view controller.
self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
UIViewController *mainDetailVC = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]]
instantiateViewControllerWithIdentifier:#"mainDetailVC"];
[self.splitViewController showDetailViewController:mainDetailVC sender:self];

How to set UIWebView initial position?

How to set the initial focus in a HTML page using UIWebView. For example, below is the HTML page. If i load this in UIWebView, it shows from (0,0) coordinates of a HTML view. But i want to change the starting position as described in the below image. I tried to change the offset, but no use.
webView.scrollView.contentOffset = CGPointMake(100, 100).
You probably shouldn't hard code this because for one reason, it's hard-coded. If google, or whatever website you want to display alters their layout your positions will be obsolete. And you will have to resubmit your entire app just to off-set this.
My recommendation is use auto layout and 'scales page to fit' for the UIWebView.
But your code is accurate. Make sure you put it in webViewDidFinishLoad: or viewDidLoad and your UIWebViewDelegate & UIScrollViewDelegate are added to your header file and called in your implementation file :
self.webView.delegate = self;
self.webView.scrollView.delegate = self;
Place the UIWebView into a subview. A generic UIView will work.
When instantiating the UIWebView, give it screen bounds with a slightly lower width than the containing UIView. Weird, I know.
Set the UIWebView's contentOffset in the webViewDidFinishLoad method of your UIWebViewDelegate
The following code works for me, in Xcode 6.1.1. To test, just make this ViewController class the root view controller for your app:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
override func loadView () {
let screenBounds : CGRect = UIScreen.mainScreen().bounds
var slimmerBounds : CGRect = UIScreen.mainScreen().bounds
slimmerBounds.size.width = slimmerBounds.size.width - 1
let webView = UIWebView(frame: slimmerBounds)
let url = NSURL (string: "http://google.com/")
let req = NSURLRequest(URL: url!)
webView.loadRequest(req)
webView.delegate = self;
let contentView = UIView(frame: screenBounds)
contentView.addSubview(webView)
self.view = contentView
}
func webViewDidFinishLoad(webView: UIWebView) {
webView.scrollView.contentOffset = CGPointMake(0, 100)
webView.bounds = UIScreen.mainScreen().bounds
}
}
By the way ... this will set the initial position of all URLs loaded into this Web view. If you only want to position the first page, you'll need to add some additional logic to webViewDidFinishLoad

about positioning myself,some problems

I am a new to google map sdk for ios.I have added a map on a view.When I enter this mapView,I want to positioning myself.So I wrote :
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.8683
longitude:151.2086
zoom:6];
_iMapView = [GMSMapView mapWithFrame:CGRectMake(0, 0, 320, 480) camera:camera];
self.iMapView.myLocationEnabled = YES;
self.iMapView.delegate=self;
GMSMarkerOptions *annotation = [[GMSMarkerOptions alloc] init];
annotation.position = CLLocationCoordinate2DMake(-33.8683, 151.2086);
annotation.title = #"Sydney";
annotation.snippet = #"Australia";
//annotation.infoWindowAnchor=CGPointMake(0.5, 0.5);
[self.iMapView addMarkerWithOptions:annotation];
//[self.view addSubview:self.iMapView];
self.view=self.iMapView;
but I find the mapView view in the coordinate(33.8683,151.2086),I just want to move the mapView to the wyposition. I also find google have no callback function reference to
self.iMapView.myLocationEnabled = YES;
thank you for you reply.
To animate/set the camera to your current position you first have to:
self.googleMapsView.myLocationEnabled = YES;
Then in the documentation of the GMSMapView header file you will find the following comment:
/**
* If My Location is enabled, reveals where the user location dot is being
* drawn. If it is disabled, or it is enabled but no location data is available,
* this will be nil. This property is observable using KVO.
*/
#property (nonatomic, strong, readonly) CLLocation *myLocation;
So you can setup a key value observer in your viewWillAppear Method and then you get your location update with the Location Manager of the GoogleMaps SDK.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Implement here to check if already KVO is implemented.
...
[self.googleMapsView addObserver:self forKeyPath:#"myLocation" options:NSKeyValueObservingNew context: nil]
}
And then observe the property.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"myLocation"] && [object isKindOfClass:[GMSMapView class]])
{
[self.googleMapsView animateToCameraPosition:[GMSCameraPosition cameraWithLatitude:self.googleMapsView.myLocation.coordinate.latitude
longitude:self.googleMapsView.myLocation.coordinate.longitude
zoom:self.googleMapsView.projection.zoom]];
}
}
Do not forget to deregister your observer in the viewWillDisappear.
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Implement here if the view has registered KVO
...
[self.googleMapsView removeObserver:self forKeyPath:#"myLocation"];
}
Best regards
NOTE: This answer is wrong, see Robert's answer.
The Google Maps SDK for iOS doesn't have any delegate to let you know when the device's position has changed.
You would need to use the CLLocationManager class yourself, to get the device's current position, and then update the map view.
UPDATE:
To update the map view from the new CLLocation provided by the location manager, you do something like this:
GMSMapView* mapView = ...;
CLLocation* location = ...;
GMSCameraPosition* camera = [GMSCameraPosition
cameraWithLatitude: location.coordinate.latitude
longitude: location.coordinate.longitude
zoom: 6];
mapView.camera = camera;
Or if you want the map view to animate to the new location, then use this:
[mapView animationToCameraPosition: camera];

how to find current loaded viewcontroller?

I have an tabBarController app with 2 tabBarItems.
each viewControllers contains tableView.
On didSelectRowAtIndexPath i am loading the detailview with this lines of code:
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:[NSBundle mainBundle]];
detailViewController.selectedDetail = [selectedDetail valueForKey:#"cardText"];
detailViewController.selectedCardTitle2 = [selectedCardTitle valueForKey:#"cardTitle"];
detailViewController.selectedRow2 = [self.tableViewInbox indexPathForSelectedRow];
detailViewController.detailCardsArray = allCards;
detailViewController.detailAllFetchedCards = allFetchedCards;
detailViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[inboxViewController presentModalViewController:detailViewController animated:YES];
Problem is, when detailView is loaded(is the actual shown viewController) and i change to the other tabBarItem, the detailView DOES NOT DISMISS. That means, that i cant load the detailView again, if didSelectRowAtIndexPath is called.
In my AppDelegate i have the method
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
In this method i will check up, if the detailView is the actual shown viewController.
And if it is, and the tabBarItem changes, THEN dismiss the DetailView.
Now my question is: How can I CHECK, if the detailView is loaded (current shown view) or not?
The documentation tells us that the detailView becomes a child of the presenting view. The presenting view controller will have it's modalViewController property updated to point to the presented view. Also, the modal view's parentViewController will be updated to point to the presenting view.
So, you could check these properties to see whether or not the modal view is displayed or not.

Problem using [window insertSubview]

When I use the following code to insert a view on top of a split view, I am getting orientation problems.
Here is the code I use,
[window addSubview:aSplitViewController.view];
[window insertSubview:aViewController.view aboveSubview:aSplitViewController.view];
What happens here is that the view controller ( which contains labels and buttons) loads in landscape mode while its components load in portrait mode...
I feel that the window insertSubview is creating this problem because when I used [window addSubview:aViewController.view] the view is getting displayed properly in landscape mode with its components in landscape mode as well...
Here is the code which I feel is giving me the problem
In my App Delegate
- (void) makeSplitViewController {
NSMutableArray *controllers = [NSMutableArray arrayWithArray:tabBarController.viewControllers];
// First tabbbar item
// detail view
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
UINavigationController *navDetailView = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
navDetailView.hidesBottomBarWhenPushed = YES;
// root view
rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
rootViewController.detailViewController = detailViewController;
rootViewController.navigationItem.title = #"List";
UINavigationController *navRootView = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
navRootView.hidesBottomBarWhenPushed = YES;
navRootView.navigationBar.barStyle = UIBarStyleBlackTranslucent;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.tabBarItem.title = #"Face Sheet";
splitViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
splitViewController.navigationItem.title = #"Face Sheet";
splitViewController.viewControllers = [NSArray arrayWithObjects:navRootView, navDetailView, nil];
splitViewController.delegate = detailViewController;
splitViewController.hidesBottomBarWhenPushed = YES;
[controllers addObject:splitViewController];
// Second tabbbar item
scoreViewController = [[ScoreCardViewController alloc] initWithNibName:#"TableViewController" bundle:nil];
scoreViewController.tabBarItem.title = #"Score Card";
scoreViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
scoreViewController.navigationItem.title = #"Score Card";
[controllers addObject:scoreViewController];
tabBarController.viewControllers = controllers;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Create tabbar
tabBarController = [[UITabBarController alloc] init];
//tabBarController.delegate = self;
// Set window
[window addSubview:splashController.view];
[window insertSubview:tabBarController.view belowSubview:splashController.view];
[self.window makeKeyAndVisible];
application.statusBarOrientation = UIInterfaceOrientationLandscapeRight;
return YES;
}
and here is the code in my SplashScreenView
- (IBAction) proceedButtonClick:(id)sender
{
// Initialize loginpopview
PhysicianLoginViewController *loginViewController = [[PhysicianLoginViewController alloc] init];
popOverController = [[UIPopoverController alloc] initWithContentViewController:loginViewController];
popOverController.popoverContentSize = CGSizeMake(350, 200);
popOverController.delegate = self;
// Set a notification to dismiss it later
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loginViewControllerDone:) name:#"loginViewControllerDone" object:popOverController.contentViewController];
// Present popover
if ([popOverController isPopoverVisible])
{
[popOverController dismissPopoverAnimated:YES];
}
else
{
[popOverController presentPopoverFromRect:CGRectMake(485, 600, 100, 100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
}
// Dismiss popview controller and setup the tabbar
- (void)loginViewControllerDone:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Button in content view controller was tapped, dismiss popover...
[self.popOverController dismissPopoverAnimated:YES];
// remove subview
[self.view removeFromSuperview];
// set tabbar
i3EAppDelegate *appDelegate = (i3EAppDelegate *) [[UIApplication sharedApplication]delegate];
[appDelegate makeSplitViewController];
}
It would be great if someone could point out where I am going wrong. I have been stuck with this problem for quite a few days and I have tried everything that comes to my mind...
Your problem is that the rotation handling of UIWindow and UIViewController just isn't designed to work that way. Quoth the documentation:
In an iOS application, the window object does much of the work associated with changing the current orientation. However, it works in conjunction with the application’s view controllers to determine whether an orientation change should occur at all, and if so, what additional methods should be called to respond to the change. Specifically, it works with the view controller whose root view was most recently added to, or presented in, the window. In other words, the window object works only with the frontmost view controller whose view was displayed using one of the mechanisms described in “Presenting a View Controller’s View.”
This paragraph is somewhat vague and contradictory (is it the most recently added view controller, or the controller for the topmost view?), and in practice doesn't seem to necessarily match observations. The bottom line is that adding multiple views to a UIWindow will screw up the automatic rotation handling.
You should change your code to use presentModalViewController:animated: (maybe with modalPresentationStyle set to UIModalPresentationFormSheet) or a UIPopoverController instead of adding multiple subviews to the window.
Try:
[aViewController.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];