I have the following setup:
A UIPageviewController that has two child-ViewControllers.
ViewController 1 contains a UITableView, ViewController 2 holds a camera setup (AVCaptureSession, etc). It's basically a Snapchat like setup.
Swiping between the two works perfectly - swipe left, UITableView is showing, swipe right and the camera shows up again. So far so good.
Now I want to implement a button that turns the page to get to the controller that hold the UITableView programatically. Here's how I do it:
let startingViewController = self.viewControllerAtIndex(0)
let viewControllers: [UIViewController] = [startingViewController!]
pageViewController!.setViewControllers(viewControllers, direction: .Reverse, animated: true, completion: nil)
This works for the most part, as it slides out the UIViewController holding the camera instance and slides in the one holding the UITableView. However, it seems like the view controller that holds the camera session is deallocated, so when I swipe right again, the camera has to be fired up again. Is there any way to turn the page differently, without having the camera session deallocated?
I have tried adding the camera to the PageViewcontroller and adding an "invisible" overlay, but this is not the solution I am looking for. Can someone help out here?
The correct way to do this is using a UIScrollView with multiple subviews and paging enabled. When you press the button, you do not "turn the page", you manipulate/animate the content of the scroll view.
For further reference:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/UIScrollView_pg/ScrollViewPagingMode/ScrollViewPagingMode.html
Related
I'm developing a SpriteKit game with two different scenes (MainMenu.sks and Settings.sks). I also have a UIViewController.
From the MainMenu the user can tap "Settings" which causes the app to load the Settings.sks scene and present it.
It's done using this code:
// Move to Settings.sks
let transition = SKTransition.flipVertical(withDuration: 1.0)
let loadScene = SettingsScene(fileNamed: "SettingsScene")
loadScene?.scaleMode = self.scaleMode
self.view?.presentScene(loadScene!, transition: transition)
From the Settings.sks scene the user can tap on the SKLabelNode "Change username" which causes the app to load the UIViewController by performing a segue.
The UIViewController contains a UITextField and a UIButton. The UIButton takes the user back to MainMenu.sks.
However, when I'm doing so the it's like a new scene of MainMenu is placed upon the other causing the app to sort of "freeze" and not responding to any touch gestures. I can see from the nodeCount that the nodes are doubled.
A workaround is loading the UIViewController directly from the MainMenu.sks (also via a segue). By doing so, the app works just fine.
I'm suspecting the problem to be the way I load Settings.sks.
What am I missing? Maybe unloading the entire SKView before exiting?
Performing a segue will present a new view on top of the stack. By using a segue to return to the main menu, the app will create a new main menu on top of the UIViewController. I can't say for certain why your app freezes. But I would guess that there are some properties or functions that don't work properly when a new main menu is created and presented from your UIViewController.
I recommend unwinding the segue used to reach the UIViewController instead. This way you can return to the previous view and conserve memory.
You'll need to write an IBAction in your destination view, the main menu in this case:
#IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
}
Then ctrl-drag from your button in the UIViewController to the exit icon in storyboard. You should see an option to use the IBAction unwindToMainMenu that you just wrote. This will create an unwind segue.
A complete guide to unwind segues and multiple examples can be found in this answer: What are Unwind segues for and how do you use them?
I have a tabbed application with three tabs and I want to make the transition between them with a Swipe Gesture Recogniser.
I dragged and dropped one Swipe Gesture Recogniser from the Object Library to the first View and one to the third View. I added two on the second View so I can swipe both left and right.
I changed the Swipe to the Attribute Inspector so it will swipe right or left as needed
Using the Assistant editor I used Control+Drag to create Actions to the proper ViewController.swift files.
What else should I do so the swiping should work?
All of the guides I found online are in Objective-C. Does anyone know how to complete these Events in Swift?
You have to apply custom view controller transitions. Otherwise your tab transition will be neither animated (by default tab switches are without animation) nor interactive (you cannot control the speed with your gesture).
A good starting point is Colin Eberhardt's VC Transitions Library. It's in Objective-C but you can use it from Swift.
Just a warning: Custom view controller transitions are an immature part of iOS 7 or 8. If another view transition is initiated while a custom one is still running, the UI will more or less lock up. And it easily happens: user presses yet another tab before the transitions ends, your code switches tab and pushes a view controller at the same time, user manages to press a button during transition that opens another view controller etc.
EDIT: I have added a sample project to github and it fully works. Feel free to copy it or wok on it.
You don't need to add them in the story board. First add this code to your initializer (in most cases viewDidLoad):
var swipeGesture = UISwipeGestureRecognizer(target: self, action: "SwipeToNextViewController:")
swipeGesture.direction = UISwipeGestureRecognizerDirection.Left
view.addGestureRecognizer(swipeGesture)
var swipeGestureReverse = UISwipeGestureRecognizer(target: self, action: "SwipeToPreviousViewController:")
swipeGestureReverse.direction = UISwipeGestureRecognizerDirection.Right
view.addGestureRecognizer(swipeGestureReverse)
Now that your viewController has the gesture, SwipeToNextViewController() will be called if you swipe left, and SwipeToPreviousViewController() will be called when swiped Right.
Write the code for the two functions associated with the gestures:
func SwipeToNextViewController(gestureRecognizer:UISwipeGestureRecognizer)
{
performSegueWithIdentifier("next", sender: self)
}
func SwipeToPreviousViewController(gestureRecognizer:UISwipeGestureRecognizer)
{
performSegueWithIdentifier("previous", sender: self)
}
These two functions will be called when view has been swiped left or right. Add your code in it (in this case performSegue) and you can segue to another viewController.
Hope it helps :)
I currently have a segue that presents a VC modally in PresentationStyle.PageSheet. I have done this both programmatically and with just the storyboard. I get the same result with both approaches, the modal pop over presents itself but does not show any content inside the UIView from the VC. It will only show the background color of the view and that is all. I also want to point out that everything is displayed if I do a default modal segue (full screen) but fails with page sheet presentation style or with using UIPopoverController. Here are some screen shots that show what I am talking about.
This is what it looks like in the storyboard:
This is what it looks like in the simulator and on an actual ipad:
Here is what my coding approach looked like:
#IBAction func addPickUp(){
var addPickupVC = self.storyboard?.instantiateViewControllerWithIdentifier("pickup") as AddPickupViewController
addPickupVC.modalPresentationStyle = UIModalPresentationStyle.PageSheet
self.presentViewController(addPickupVC, animated: true, completion: nil)
}
This written in swift for ipad ios8.
What am I missing here? Any constructive feed back is appreciated!
EDIT: Here is the document outline of the VC that is to presented modally.
Your code for presenting popover is correct.
Probably there is problem with AutoLayout constraints.
As you can see your popover is presented but label is missing.
Remove your AutoLayout (they will be auto generated) and see if the label will be visible now
Try to add new label. Drag and drop it, and don't specify any constraints
Debug your view
Click "Debug view hierarchy" button at the debug panel
Now you can see your view hearty. Select your label, if it's present and see it's constraints.
Check your AutoLayout constraints and Label is present in correct Size Classes
Size classes is shown bellow UI designer. In my case it's (Any Any).
It means that it's for all sizes and all devices.
Also check that your constrains is not removes at runtime.
You can see it on inspector in right side.
In the storyboard, you can simply control drag a connection from your button to your presented Viewcontroller. There's no reason to have a #IBAction for this. If you use the InterfaceBuilder approach you can optionally set the presentation style on the segue to PageSheet.
I have a situation here which I am trying to resolve, but it seams I am missing something.
My architecture of the application is as following:
AppDelegate (TabBarController)
Navigation Controller
Viewcontroller one
Viewcontroller two
Viewcontroller three
Viewcontroller
Since I have lot of text validations and scrolling enabled, I am using a custom uiscrollview for viewcontroller one, two and three. In the custom uiscollview I am utilizing the code from Apple which causes scrollview to scroll if the textfield is being hidden behind the keyboard. The problem which I am occuring at this point is that I have the viewcontroller one working fine, but when it comes to viewcontroller two and three, it does see's that custom view controller after debugging, and reaches the point of "setContentOffSet" but not animating the scrollview, but just displaying the keyboard.
If anyone had this issue before, I would like to see what might I be missing here?
I'm currently working with 2 views on a UINavigationController.
I have a Leaves view (Tom Brow's leaves project) to simulate curling effect for pages which only works with images, and my actual view controller with the page and it's contents.
What I'm trying to do is, when tapped on certain place, popViewControllerAnimated:NO the actual view controller, leaving the leaves view behind on top and trying to do the page turn without having to tap again on the screen and keeping things as if no switch ever happened.
My issue here is that the touches seem to go through a black hole and never get to the current view. I've even tried to catch the touches with a custom UIApplication subclass, but as soon as the first view gets popped the touches start coming with nil view and window and phase = UITouchPhaseStationary.
The views in the navigation controller are pushed: one as the rootViewController in the init method and the other with a pushViewController:animated:.
Is there something I'm missing or there's just no way to keep touches through views in a UINavigationController?
EDITED: Final solution, clear overlay to get touches