I use isHideStatusBar(true) and override two essential props for hide and show StatusBar in viewController
var statusBarShouldBeHidden = false
override var prefersStatusBarHidden: Bool {
return statusBarShouldBeHidden
}
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
func isHideStatusBar(_ bool: Bool, _ delay : CFTimeInterval = 0){
statusBarShouldBeHidden = bool
UIView.animate(withDuration: 0.4, delay: delay, options: [], animations: {
self.setNeedsStatusBarAppearanceUpdate()
}) { (finished) in
}
}
how to put some line of this code in to UIViewController extension ?
Can be with a subclass
class MainViewController: UIViewController {
var statusBarShouldBeHidden = false
override var prefersStatusBarHidden: Bool {
return statusBarShouldBeHidden
}
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
func isHideStatusBar(_ bool: Bool, _ delay : CFTimeInterval = 0){
statusBarShouldBeHidden = bool
UIView.animate(withDuration: 0.4, delay: delay, options: [], animations: {
self.setNeedsStatusBarAppearanceUpdate()
}) { (finished) in
}
}
}
class ViewController: MainViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
isHideStatusBar(true)
}
}
Extension ability is limited to contain stored properties & overrided methods
Related
I'm using the coordinator pattern in my code to transition from the RootNavigationController to a SplashScreenViewController
class AppCoordinator {
let window: UIWindow
let rootViewController: RootNavigationController
init(window: UIWindow) {
self.window = window
rootViewController = RootNavigationController()
let splashScreenViewController = SplashScreenViewController()
rootViewController.pushViewController(splashScreenViewController, animated: false)
}
}
extension AppCoordinator: Coordinator {
func start() {
window.rootViewController = rootViewController
window.makeKeyAndVisible()
}
}
I'm also using a custom transition to handle the transition from RootNavigationController to SplashScreenNavigationController.
class FadeInAnimator: NSObject {
var duration: TimeInterval = 1.0
}
extension FadeInAnimator: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toViewController = transitionContext.viewController(forKey: .to) else { return }
containerView.addSubview(toViewController.view)
toViewController.view.alpha = 0
let durationOfTransition = transitionDuration(using: transitionContext)
UIView.animate(withDuration: durationOfTransition, delay: 0, options: [.curveEaseIn], animations: {
toViewController.view.alpha = 1
}) { (finished) in
transitionContext.completeTransition(finished)
}
}
}
I've set the delegate of the RootNavigationController to it's self and implemented the animation transitioning however, when I start the application it seems to just ignore everything I've done and just use the systems default transition.
This is the code in the RootNavigationController
class RootNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationBar.shadowImage = UIImage()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
extension RootNavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
switch operation {
case .push: return FadeInAnimator()
case .pop: return nil
case .none: return nil
}
}
}
Remove open & close bracket
UIView.animate(withDuration: durationOfTransition, delay: 0, options: .curveEaseIn, animations:
I want to retrieve the value from the scrollViewDidScroll function at my view controller. It gives the right value back in the console so that's nice.
My view controller:
import UIKit
extension UIPageViewController: UIScrollViewDelegate {
public override func viewDidLoad() {
super.viewDidLoad()
for subView in view.subviews {
if subView is UIScrollView {
(subView as! UIScrollView).delegate = self
}
}
}
public func scrollViewDidScroll(scrollView: UIScrollView) {
let point = scrollView.contentOffset
var percentComplete: CGFloat
percentComplete = fabs(point.x - view.frame.size.width)/view.frame.size.width
print("percentComplete: ", percentComplete)
}
}
class StepsDetailViewController: UIViewController {
var pageIndex: Int!
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Where the view controller came from:
import UIKit
class PageControl: UIPageViewController, UIPageViewControllerDataSource {
var pageViewController: UIPageViewController!
var pageTitles: [[String]]!
override func viewDidLoad(){
super.viewDidLoad()
testC().getRecent() { result, error in
self.pageTitles = result;
self.pageViewController = self
self.pageViewController.dataSource = self
let startVC = self.viewControllerAtIndex(0) as StepsDetailViewController
dispatch_async(dispatch_get_main_queue(), {
let viewControllers = NSArray(object: startVC)
self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: .Forward, animated: true, completion: nil)
})
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func viewControllerAtIndex(index: Int) -> StepsDetailViewController
{
if ((self.pageTitles.count == 0) || (index >= self.pageTitles.count)) {
return StepsDetailViewController()
}
let vc: StepsDetailViewController = self.storyboard?.instantiateViewControllerWithIdentifier("StepsDetailViewController") as! StepsDetailViewController
vc.pageIndex = index
return vc
}
// MARK: - Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
let vc = viewController as! StepsDetailViewController
var index = vc.pageIndex as Int
if (index == 0 || index == NSNotFound)
{
return nil
}
index -= 1
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let vc = viewController as! StepsDetailViewController
var index = vc.pageIndex as Int
if (index == NSNotFound)
{
return nil
}
index += 1
if (index == self.pageTitles.count)
{
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.pageTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}
}
Is this possible?
You could do like this:
1. Replace your extension with a custom UIPageViewController
class BasePageViewController: UIPageViewController, UIScrollViewDelegate {
var percentComplete: CGFloat = 0.0 {
didSet { self.percentCompleteDidChange() }
}
func percentCompleteDidChange() {
print("percentCompleteDidChange")
}
public override func viewDidLoad() {
super.viewDidLoad()
for subView in view.subviews {
if subView is UIScrollView {
(subView as! UIScrollView).delegate = self
}
}
}
public func scrollViewDidScroll(scrollView: UIScrollView) {
let point = scrollView.contentOffset
self.percentComplete = fabs(point.x - view.frame.size.width)/view.frame.size.width
print("percentComplete: ", percentComplete)
}
}
2. PageControl is a BasePageViewController subclass
class PageControl: BasePageViewController, UIPageViewControllerDataSource {
// here you have the access to percentComplete of superclass
func printPercentComplete() {
if let percentComplete = self.percentComplete {
print(percentComplete)
}
}
override func percentCompleteDidChange() {
print("percentCompleteDidChange from child")
}
......
}
Define the percentComplete as a property of your custom class that inherits from UIPageViewController.
Then you can access it everywhere.
import UIKit
import Alamofire
import SystemConfiguration
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var simpleLabel: UILabel!
#IBOutlet weak var uiNameSearch: UITextField!
#IBOutlet weak var uiGivenName: UITextField!
var patient1 = Patient!()
override func viewDidLoad() {
super.viewDidLoad()
uiNameSearch.delegate = self
uiGivenName.delegate = self
print("ViewController viewDidLoad")
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.simpleLabel.center.x -= self.view.bounds.width
self.uiGivenName.center.x -= self.view.bounds.width
print("Call viewWillAppear")
}
override func viewDidAppear(animated: Bool){
super.viewDidAppear(animated)
UIView.animateWithDuration(0.9 , animations: {
// self.simpleLabel.center.x += self.view.bounds.width
self.uiGivenName.center.x += self.view.bounds.width
})
UIView.animateWithDuration(0.7 , delay: 0.7, options: [], animations: {
self.uiNameSearch.center.x += self.view.bounds.width
}, completion: nil )
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func searchForName(sender: UIButton) {
let header = ["Accept" : "application/json"]
let name = uiNameSearch.text!
let given = uiGivenName.text!
if name.characters.count == 0 {
self.view.makeToast( message: "Please insert the family name of the patient!")
} else if given.characters.count == 0 {
self.view.makeToast(message: "Please insert the patient given name!")
} else if checkInternetConnection() == false {
self.view.makeToast(message: "Please connect to the internet!")
} else {
Alamofire.request(.GET, "https://open-ic.epic.com/FHIR/api/FHIR/DSTU2/Patient?family=\(name)&given=\(given)", headers: header).responseJSON { response in
self.patient1 = Patient(response: response.result.value!)
self.performSegueWithIdentifier("showSegue", sender: sender)
}
}
}
func checkInternetConnection() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
switch textField {
case uiNameSearch:
uiNameSearch.resignFirstResponder()
uiGivenName.becomeFirstResponder()
case uiGivenName:
uiGivenName.resignFirstResponder()
default:
print("")
}
return true
}
override func prepareForSegue(segue: UIStoryboardSegue, sender:AnyObject?){
if segue.identifier == "showSegue" {
if let displayViewController = segue.destinationViewController as? DisplayViewController {
displayViewController.patient1 = patient1
}
}
}
}
I want to make uiGivenName and simpleLabel to disappear until the view is created and after when the viewDidAppear is invoked to appear from the left side.
Your view doesn't disappear because you are changing position of views in viewWillAppear and when viewWillAppear gets called, view is about to be added to view hierarchy(i.e view is still not added to view hierarchy.), so its not reflecting in your UI.
So you can do your stuff in viewDidLayoutSubviews because this is the best place if you want to modify your UI just before it actually appears in the screen.
Edit -
Replace this -
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.simpleLabel.center.x -= self.view.bounds.width
self.uiGivenName.center.x -= self.view.bounds.width
print("Call viewWillAppear")
}
with
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.simpleLabel.center.x -= self.view.bounds.width
self.uiGivenName.center.x -= self.view.bounds.width
}
I've tried to create a class in Swift, which autohides my UIStatusBar and my navigationController after 1 Second.
My problem is, that the StatusBar is not going to disappear. This is what I got:
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "prefersStatusBarHidden", userInfo: nil, repeats: false)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return UIStatusBarAnimation.Fade
}
override func prefersStatusBarHidden() -> Bool {
if (barcounter == 0){
hide()
barcounter = 1
return true
}
else {
show()
barcounter = 0
return false
}
}
#IBAction func picturePressed(sender: AnyObject) {
prefersStatusBarHidden()
}
func hide(){
UIView.animateWithDuration(1, delay: 1, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.navigationController?.navigationBar.alpha = 0.0
}, completion: nil)
}
func show(){
UIView.animateWithDuration(1, delay: 1, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.navigationController?.navigationBar.alpha = 1.0
}, completion: nil)
}
You need to override this method in whichever view controller u want to hide uistatusbar.
override func prefersStatusBarHidden() -> Bool {
return true;
}
if its not work then try this:-
In Info.plist set View controller-based status bar appearance to NO
And call UIApplication.sharedApplication().statusBarHidden = true
hope this helps you.
Alright.. I solved it like that:
I created a new class HeaderAnimationHelper in which I created the useable methods. Like that I can call it from everywhere.
So here you can see the Helper class:
import UIKit
class HeaderAnimationHelper {
static let sharedInstance = HeaderAnimationHelper()
var navi: UINavigationController!
func hideController(var barcounter: Int, navigationController: UINavigationController) -> Int {
navi = navigationController
if (barcounter == 0){
barcounter = 1
UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: UIStatusBarAnimation.Fade)
hide()
}
else {
show()
barcounter = 0
UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: UIStatusBarAnimation.Fade)
}
return barcounter
}
func hide(){
UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.navi.navigationBar.alpha = 0.0
}, completion: nil)
}
func show(){
UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.navi.navigationBar.alpha = 1.0
}, completion: nil)
}
}
and the next class is the main class in which you can put all you code and stuff...
I created it like that:
import UIKit
class ContactMeViewController: UIViewController {
var barcounter = 0
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "animate", userInfo: nil, repeats: false)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return UIStatusBarAnimation.Fade
}
#IBAction func picturePressed(sender: AnyObject) {
animate()
}
func animate(){
barcounter = HeaderAnimationHelper.sharedInstance.hideController(barcounter, navigationController: self.navigationController!)
}
}
edit 10/07/15:
I've forgotten to mention, that it's important to add the dependency to the Info.plist
In Info.plist set View controller-based status bar appearance to NO
Watch out this method UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: UIStatusBarAnimation.Fade)
is depricated
I have correctly set up a UIPageViewController.
I would like to check the itemIndex of each views and display content accordingly. Here's what the code looks like:
var itemIndex: Int = 0 {
didSet {
if itemIndex == 1 {
println("Character is Lela!")
}
if itemIndex == 0 {
println("Character is John!")
}
}
}
What I tried
I run the app
Console Output: "Character is John!"
I swipe forward (to the right)
Console Output: "Character is Lela!"
I swipe back (to the left)
There is no output!
I swipe forward
There is no output! Again!
What is this due to? Here's the full code:
import UIKit
var currentIndex: Int = 0
var nextIndex: Int = 0
class ProView: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var pageViewController: UIPageViewController?
let characterImages = ["character1", "character2", "character1", "character2", "character1", "character2", "character1", "character2"]
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControl()
character = 1
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// Forward, check if this IS NOT the last controller
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController ProView: UIViewController) -> UIViewController? {
let itemController = ProView as PageItemController
// Check if there is another view
if itemController.itemIndex+1 < characterImages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
// Check if this IS NOT the first controller
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController ProView: UIViewController) -> UIViewController? {
let itemController = ProView as PageItemController
if itemController.itemIndex < 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
private func getItemController(itemIndex: Int) -> PageItemController? {
if itemIndex < characterImages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as PageItemController
pageItemController.itemIndex = itemIndex
pageItemController.imageName = characterImages[itemIndex]
return pageItemController
}
return nil
}
func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
pageController.dataSource = self
pageController.delegate = self
if characterImages.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController?.didMoveToParentViewController(self)
}
func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return characterImages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
// BETA
func pageViewController(PageItemController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers pageViewController: [AnyObject],
transitionCompleted completed: Bool)
{
if (!completed)
{
// You do nothing because whatever page you thought
// the book was on before the gesture started is still the correct page
return;
}
// This is where you would know the page number changed and handle it appropriately
}
}
class PageItemController: UIViewController {
#IBOutlet weak var imageCharacterChoose: UIImageView!
var itemIndex: Int = 0 {
didSet {
if itemIndex == 1 {
println("Character is Lela!")
}
if itemIndex == 0 {
println("Character is John!")
}
}}
var imageName: String = "" {
didSet {
if let imageView = imageCharacterChoose {imageCharacterChoose.image = UIImage(named: imageName)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
imageCharacterChoose!.image = UIImage(named: imageName)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
didSet and willSet will only get called when you change the value of the corresponding variable, so in your case you should somewhere in your code do itemIndex = 1, or some other value to trigger the functions.