segue from SCNNode object (Swift) - swift

I am using XCode 6 beta 5 with Swift / Scenekit. I have a SCNNode (a 3D SCNText object) that I want to use as a button. How do I connect this to a segue? With storyboard or programmatically? I thought of connecting the code for the SCNNode to a hidden button on the story board which connects to the segue but that seemed kinda hackish.

This is the same case as performing a segue from a map annotation, dynamically choosing between multiple segues from the same table cell, performing a segue in response to SpriteKit event handling, or any other case where you need to perform a segue in response to something that happens in your code instead of in response to the user tapping a control you set up in IB. You need a "manual" segue.
In the storyboard, create a segue by dragging from the (source) view controller itself to the destination view controller (instead of by dragging from a button or other control). Define an identifier for the segue using the inspector pane.
When something happens in your code that should trigger the segue, call performSegueWithIdentifier: with the identifier you defined. (If this code is inside of the view controller class, you can call it on self. Otherwise you'll need a reference to the view controller to segue from.)
As #FlippinFun points out, you can find code for touch handling in the SceneKit Game Xcode template. (For those following along at home, the gist of it is to use the view's hitTest method to find the scene element at the touch/click location.) In there is where you'd call performSegueWithIdentifier.
But there's a problem -- that template puts its touch handling code inside a view class instead of in the view controller, so the touch handling code doesn't know about the current view controller. Some possible solutions, ranked from "Best MVC architecture" to "Most quick-and-dirty":
Instead of subclassing SCNView to implement touch handling code, use a UITapGestureRecognizer instance instead -- it can call an action method on your view controller, and then you can use the recognizer's locationInView method to get a point you can hitTest with. Since you're still in view controller code there, you can call self.performSegueWithIdentifier once you get a hit-test result you like.
In the SCNView subclass, keep a (weak!) reference to the view controller that owns it. Then the view's touch handling code can call performSegueWithIdentifier on that view controller. (If you want to keep things abstract so the view doesn't have to know the view controller class, define a protocol.)
In the SCNView subclass' touch handling code, use self.window.rootViewController to find the view controller, and cast the result to your view controller class.

As far as using the text as a button, load up a new project with the rotating cube. Inside of the handleTouches is exactly what you are looking for.

Related

iOS - ViewController access into a cocoa touch class

I have been working on an app, and I have a cocoa touch class file called Tiles. Inside this class I have applied sizeConstraints to each of my tiles. I started off to set these sizeConstraints as a constant, so it would work on a certain device. I made sure it worked on that device, then I decided I would then change the constant to zero, and set it as a multiplier of a UIView inside my ViewController. Inside my ViewController I have a containerView, it is just a UIView that is going to hold my tiles. The problem is, I am unable to access the containerView inside my Tiles class and therefore can not assign each Tile to be of a certain multiplier of my containerView. I do the positionConstraints inside my ViewController, which is simple to do and has been done, but to get the exact size of the actual Tiles is not working for me. Thanks for any help!
Welcome to Stack Overflow.
Your question is worded strangely and it's a bit hard to figure out what you're asking.
I THINK you are saying that you have a parent view controller that has one or more container views that host other child view controllers, linked with embed segues. Your child view controllers will be responsible for "tiles" of your parent view controller's window.
Further, you want your child tile view controllers to have access to the container view that they are contained in.
Is that right?
If so, the short answer is "don't do that." You should treat another view controller's views as private.
What you should do is build a protocol that your parent view controller can use to communicate with the tile view controllers. Say you give each tile view controller a property "tileHostVC" that conforms to a protocol TileHostVCProtocol.
Then in the prepareForSegue method of your parent view controller, check for the identifiers of your embed segues, and you see one, set up the tile's tileHostVC property.
Now, in your tile VCs, you can send messages (defied in your TileHostVCProtocol) to the host view controller to ask it questions or request services.

How can I get a custom UIControl to participate in a segue as a push action?

I have a custom class that inherits from UIControl, to get touch events. It's basically a collection of other controls that acts as one. I'm converting my app from xibs to a storyboard. It's been mostly painless, except for this.
I drag a UIView into my scene, change the class to my custom control, hook it up to outlets on my ViewController. What I want to do with the control when it's clicked is perform a (push) segue to another ViewController. But the outlets in the designer aren't there for my UIControl to set up the segue.
Is it possible to do this? If so, what do I do to the class to enable that?
I don't think so. Looking at the Connections Inspector pane, UIButton and UIBarButtonItem instances get special treatment—an extra "triggered segues" action you can connect to adjacent view controllers:
While changing your view's class to a descendent of UIControl makes the standard suite of control events available, unfortunately Interface Builder does not let you hook up a segue. The best you can do is create a manually-triggered segue from your view controller to another, then connect your custom control to an IBAction method that performs the segue programmatically:
- (IBAction)performManualSegue:(XYZCustomControl *)sender
{
[self performSegueWithIdentifier:#"manualPushSegue" sender:sender];
}

How to create custom view controller container using storyboard in iOS 5

In iOS5 using storyboard feature I want to create a custom container which will have 2 ViewControllers embedded in it. For Example, embed Table view controller as well as a view controller both in one ViewController.
That is, one view controller will have 2 relationship:
to table view controller
to view controller which in turn will have 4 UIImage view Or UIButton in it
Is creating this type of relationship possible using storyboard's drag drop feature only & not programmatically?
,You should only have one view controller to control the scene. However, this viewController might have two other view controllers that control particular subviews on your scene. To do this you create properties in your scene viewController, in your case one for your tableViewController and one for your view. I like to keep things together so I make both these viewControllers outlets and create them in interface builder. To create them in interface builder pull in an Object from the Object library and set its type to the relevant viewController. Hook it up to the appropriate outlet you just created in your scene's viewController - Note: this is important otherwise the viewController will be released if you are using ARC and crash your app. Then hook these viewControllers up to the view you want them to control and you are done.
Alternatively you can instantiate and hop up your viewControllers in your scenes viewController should you prefer to do this.
Hope this helps.
Edit: On reflection this is not a good idea and actually goes against the HIG you should maintain only one ViewController for each screen of content and instead try to create a suitable view class and have the single view controller deal with the interactions between the various views.
There is a way to do it that isn't too hacky. It is described at the following URL for UITabBarControllers, which you could use the first view controller in the list control the first subview, and the second one control the other. Or, you can probably adapt the code to work with UISplitViewController.
http://bartlettpublishing.com/site/bartpub/blog/3/entry/351
Basically, it works by replacing the tabbarcontroller at runtime after iOS has finished configuring it.

AutorotateToInterfaceOrientation of a UIviewcontroller Inside a UITabViewController

Hi I have an iphone app in which 2 button .when I click on the one of the button there a UITabViewController with 4 tab is opened modally. I need to rotate both Portrait and lanscape the viewcontroller inside this UITabViewController. I Don't need to rotate all the view controller inside the Tabviewcontroller ,Only one viewController. Please help me .
Thanks in Advance.
any view controller you don't want rotating needs define it's own version of the shouldAutorotateToInterfaceOrientation method like this
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
To do that, you may have to subclass a specific view controller just to incorporate this one custom method
UPDATE:
It sounds like you have multiple view controllers active at once.
If you place some debug code in all of your shouldAutorotateToInterfaceOrientation methods on all of your viewcontroller based objects, my guess is only one will be receiving the notification of a rotation event.
In which case, since it is difficult to know which one will receive the rotation event notification, you will have to modify them all to disseminate the notice to each other in some way.

How does iOS know which view controller should be active?

If I want to replace one screen of an app with another, but I don't use a navbar/tabbar controller, then I could just remove oldViewController.view from window and add newViewController.view to it. That's all, now newViewController will get rotation events, etc.
But UIView does not reference "its" controller, so how is this possible, how iOS know it should make newViewController an active one? Does iOS do some magic, it internally references controller from view or what?
UPDATE:
I think I was misunderstood: I don't ask how to make some view controller an active one - I know that. I'm just curious, how is it possible that I pass some view to UIWindow object ([window addSubview:view]) and it somehow finds view controller although view doesn't know its controller.
yeh I had the same question like you. and I figured it out.
UIView is derived from UIResponder. and UIView must subclass UIResponder::nextResponder.
Its default implementation is returning a view controller of the view (if it hadn't, it would be super view)
So, consequently view can see its controller. that means window know the topmost view and also
its controller.
good luck.
Unfortunately, iOS only send events to the first ViewController of the stack. You can try and present a new one on the top of others with video for example, it will never rotate.
If you don't use navbar/tabbar controller you will have to add and remove everytime from the Window to keep only one at the time if you wand to have events.
The main UIWindow class for your application will have a view controller set in its rootViewController property. That controller's view is the "main" view for the app. This is usually setup in the main .xib for the project. That view controller will receive the usual events like "viewDidAppear" or "willRotateToInterfaceOrientation". You can put up your own view over top of it if you want to, but you will need to manage those events yourself. Usually you don't do that though. You just use a UINavigationController or UITabBarController as your rootViewController and allow them to manage getting the events to new "pushed" view controllers, or you popup view controllers with "presentModalViewController".