error passing data to tableController - uiviewcontroller

I am new to swift, and I am trying to make a lobby screen with a text field and a button to move on to the next screen. I connected it in segue to "show" the next view controller.
I need it to check my input field and only continue if the field is not empty, and of course to pass the name to the next view controller, also I cannot manage to show and hide my keyboard (stays on when segueing to the second view controller). Does anyone know how to make a button check the field and only then move to the next view controller?
here is my code(mostly auto generated):
import UIKit
class LobbyController: UIViewController {
#IBOutlet weak var playerNameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
playerNameField.becomeFirstResponder()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func nameLabel(sender: UITextField) {
playerNameField.becomeFirstResponder()
}
#IBAction func startGameButton(sender: AnyObject) {
self.playerNameField.resignFirstResponder()
}
}
thanks!

If you want to do some input validation before segueing, you should not connect the segue directly to the button, but segue from code.
First you should control click on your button and remove the segue action created.
Now you should create the segue from the view controller, by control dragging from the yellow view controller icon in the document outline.
Then, click on the segue in the storyboard and open its attributes inspector and add a segue identifier.
Now you can perform this segue in code.
So for the IBAction of your button press you can say something like:
#IBAction func startGameButton(sender: AnyObject) {
if self.playerNameField.text?.characters.count != 0{
self.playerNameField.resignFirstResponder()
self.performSegueWithIdentifier("MySegueId", sender: self.playerNameField.text!)
}
}

Related

Uiview scroll with webview

I have a webpage in WkWebview, and in the webpage there is rect region where I want to put a UIView playing live movie. I've made the webview and uiview, but I cannot figure out how to make the uiview's position to the rect region. That's to say, when user scroll the webview, the uiview scroll also scrolls. It seems the uiview is a a part of webpage. How can I fix the uiview to webpage in webview?
Thanks for any help.
For this can you go to storyboard and see if the uiview is inside the view or not and if then drag it outside and try to set its frame in property console because if you drag and drop to set uiview frame it will be gone in subview of your uiwebview
Hope it will help you
Finally I solved this by use javascript to get the regin location of webpage. Then set the UIView to that location.
Here is the code, in the webpage the regin div has tag movie, and the uiview has name player.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.wk.evaluateJavaScript("var rect = document.getElementById('movie').getBoundingClientRect();[rect.left, rect.top];") {
(result, error) -> Void in
print(result)
self.player.view.frame.origin.x = (result as! Array)[0]
self.player.view.frame.origin.y = (result as! Array)[1]
}
}

tvOS - catch MENU button presses during push-view-controller transition

I have a UIViewController in my tvOS app which will only appear for a few seconds, and needs totally customizable MENU button handling. I create it like so:
- (void)viewDidLoad
{
[super viewDidLoad];
// Add a tap gesture recognizer to handle MENU presses.
UITapGestureRecognizer *tapGestureRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGestureRec.allowedPressTypes = #[#(UIPressTypeMenu)];
[self.view addGestureRecognizer:tapGestureRec];
}
- (void)handleTap:(UITapGestureRecognizer *)sender
{
// Code to process the MENU button is here.
}
I display the view controller using pushViewController:animated::
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
[self pushViewController:controller animated:isAnimated];
I've found that if the user presses MENU as soon as the screen starts to appear, while the cross-fade transition effect is still displaying, they are able to dodge the UITapGestureRecognizer and go back to a previous screen, which is not intended. They can also cause issues by mashing MENU over and over again--eventually they will escape out of things that they should not be able to.
How can I ensure that the MENU press always reaches my override? Is there a way to specify an app-encompassing MENU button handler and still use a UINavigationController?
A solution that worked for me was to install a UITapGestureRecognizer onto self.navigationController.view. Any taps which get missed by the regular UIViewControllers end up getting caught by the navigation controller's recognizer instead. If you install UITapGestureRecognizers on each view controller you create, the only taps which will fall through the cracks to the navigation controller are taps that occur mid-transition, and it is safe to just ignore those taps completely.
Note that when you want MENU to go back to the home screen, you will need to temporarily remove this tap recognizer and let tvOS handle the tap on its own, as I could find no clean way to escape to the home screen in my code (short of exit(0)).
I have very similar problem because of this behaviour.
In my case I have custom focus management depending on MENU button click detected on pressesEnded and managed by preferredFocusedView. But when navigation controller is poping ViewController and user at this time make second click on MENU button, then UINavigationController class detect pressesEnded and then call preferredFocusedView on my destination ViewController where is my management but pressesEnded will be not called, because was "stolen" by UINavigationController.
Solution for this problem in my case is to create "dummy" class that will be used by UINavigationController like this:
class MenuPhysicalHackNavigationController: UINavigationController {
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
}
override func pressesCancelled(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
}
override func pressesChanged(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
}
}

How To Show A Modal UIViewController On A Different Storyboard Using Segues?

I have UIViewController A defined on Storyboard B. UIViewController A frame dimensions are defined to be 470 wide and 100 high.
I want to segue to UIViewController A on Storyboard B from a UIButton on Storyboard A.
else if ([segue.identifier isEqualToString:#"ModalStoryboard"])
{
NSLog(#"Show Modal UIViewController");
RSStoryboardLink *storyboardLink = segue.destinationViewController;
storyboardLink.setStoryboardName = #"ModalStoryboard";
storyboardLink.setStoryboardScene = #"ModalStoryboard";
storyboardLink.transitioningDelegate = self;
}
This segue is defined in IB to present modally (current context) and at a Preferred Explicit Size. The segue works and the UIViewController is presented but it is always presented at full screen and not at the size it is defined as - 470 x 100 in IB. It is not presented as a modal popover view.
How can I show a modal UIViewController on a different Storyboard using segues?

Swipe from one ViewController to another with Swift

I'm currently trying to connect different ViewControllers with each other using Swift, but I'm stuck and would appreciate some help in order to proceed.
What I have now is a main view and when you swipe to the right you would enter another view (like Snapchat works). I've done this using the tutorial found here.
Basically I have a ContainerViewController that store two subviews in its view hierarchy. So I can swipe back and forth between Subview 1 and Subview 2 (see illustration for an idea). Subview 2 has a button that 'modally' loads another ViewController. My question is, if it is possible, how could I make it so that when I swipe left in the "modal ViewController" I would swipe back to Subview 1?
Here is my code that controls the transition from Subview 2 (BViewController) and the modal ViewController (InfoVC):
class BViewController: UIViewController, UITabBarDelegate {
#IBOutlet var item: UIBarButtonItem!
var info: InfoVC = InfoVC(nibName: "InfoVC", bundle: nil )
func tabBar( tabBar: UITabBar!, didSelectItem item: UITabBarItem!){
if item.tag == 2{ // we are in new view controller
info.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
self.presentViewController(info, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("info hash \(info.hashValue)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And this is my ContainerViewController class where the ScrollView/swipe mechanism is made.
class ContainerViewController: UIViewController {
// Outlet used in storyboard
#IBOutlet var scrollView: UIScrollView?;
override func viewDidLoad() {
super.viewDidLoad();
// 1) Create the three views used in the swipe
var AVc: AViewController = AViewController(nibName: "AViewController", bundle: nil)
var BVc: BViewController = BViewController(nibName: "BViewController", bundle: nil)
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(BVc);
self.scrollView!.addSubview(BVc.view);
BVc.didMoveToParentViewController(self);
self.addChildViewController(AVc);
self.scrollView!.addSubview(AVc.view);
AVc.didMoveToParentViewController(self);
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = AVc.view.frame;
adminFrame.origin.x = adminFrame.width;
BVc.view.frame = adminFrame;
var BFrame :CGRect = BVc.view.frame;
BFrame.origin.x = 2*BFrame.width;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = 2 * self.view.frame.width
var scrollHeight: CGFloat = self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In summary:
What I can do already is to scroll from AViewController to BViewController (back and forth) and go from BViewController to InfoVC by pressing the tab bar item/button. What I then cannot figure out is to swipe backwards in InfoVC and reach AViewController with the same transition as when I swipe between AViewController and BViewController.
You need to add a UISwipeGestureRecognizer to your InfoVC. The easiest way, in Interface Builder, is to drag one from your Object Library onto your InfoVC. You'll see a new icon for it appear in the toolbar at the top of your IB scene. Select it, then in the Attributes Inspector, choose which direction you want the swipe to go--in your case, it's probably left to right.
Next, implement touchesBegan() and touchesEnded() methods in your InfoVC, and use the locations of the events to determine whether the user has swiped whatever distance you specify between the start and end points. If touchesEnded() is at least that distance away, then you can dismiss your InfoVC by removing it from its parent, BViewController.
Load the ViewController from your storyboard
Embed the BViewController in a UINavigation controller.
That will allow you to do all segues in a storyboard kind of fashion
// lets try to load them from the storyboard
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyboard.instantiateViewControllerWithIdentifier("navController") as UINavigationController
var BVc = navigationController
This will be a good first step. In your BVc prepare for Segue enabling and disabling the scrolling as it will interfere with the containerviews swiping. ReEnable it in your BVc's view did appear.
var parentVC = self.navigationController?.parentViewController as ContainerViewController
parentVC.scrollView?.scrollEnabled = false
You might have to do some additional work to re-receive swipe events in your modal, I am not sure.
I suggest using UIPageViewController, it was created for tasks like this and you can hide the dots bar by deleting these methods:
presentationCountForPageViewController
presentationIndexForPageViewController
For the button to work you need to add:
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) {
Here is a good tutorial:
https://www.youtube.com/watch?v=8bltsDG2ENQ

returning to a uiviewcontroller without navigationcontroller

my application has a UIViewController that isn't wrapped in a UINavigationController from it I call different UINavigationControllers each representing a state in a state machine.
calling these UINavigationControllers from code is done like this:
-(void) callState1
{
[popover dismissPopoverAnimated:YES];
UINavigationController *state1NavigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"state1Navigation"];
[self presentViewController:state1NavigationController animated:NO completion:nil];
}
in state1 there is a custom UIBarButtonItem representing the back control.
self.navigationItem.leftBarButtonItem = self.backBtn;
Is there a native code that returns to the calling UIViewController?
or should I implement the same code from callState1 in the back button calling the UIViewController, and if so how can I synchronize the data between them?
Since you are presenting the view controller (state1NavigationController) modally, you need to use the method dismissViewControllerAnimated:completion: to dismiss the state1NavigationController and go back.