Данная статья написана в развлекательных целях. Если вам интересно следить за самыми последними новостями iOS разработки и получать подборку интересных статей по этой тематике, тогда вам стоит подписаться на Телеграм-канал iOS Broadcast

Предположим, вам прилетела срочная задача: реализовать календарь, который ведет себя как физический перекидной календарь в котором на каждой странице 3 сентября.


Для начала сверстаем страницу календаря:
struct CalendarView: View {
    var body: some View {
        ZStack {
            VStack {
                ZStack {
                    Text("Сентябрь")
                        .foregroundColor(.red)
                        .font(.system(.body))
                }
                Text("3")
                    .font(.largeTitle)
            }
        }
        .overlay(
            RoundedRectangle(cornerRadius: 20)
                .stroke(.black, lineWidth: 0.5)
                .frame(width: 100, height: 100)
        )
    }
}


Теперь добавим переворот страницы используя старый добрый UIPageViewController
lazy var pageViewController = UIPageViewController(
    transitionStyle: .pageCurl,
    navigationOrientation: .vertical
)
    
override func viewDidLoad() {
    super.viewDidLoad()
    
    pageViewController.dataSource = self
        
    addChild(pageViewController)
    view.addSubview(pageViewController.view)
    pageViewController.setViewControllers([UIHostingController(rootView: CalendarView())], direction: .forward, animated: false)
}


Для того чтобы сделать бесконечный календарь достаточно 2 инстансов CalendarView:
lazy var views: [UIViewController] = [
    UIHostingController(rootView: CalendarView()),
    UIHostingController(rootView: CalendarView()),
]

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    guard let index = views.firstIndex(of: viewController) else {
        return nil
    }
    return  page(at: index - 1)
}
    
func pageViewController(_ pageViewController: UIPageViewController,
                            viewControllerAfter viewController: UIViewController) -> UIViewController? {
    guard let index = views.firstIndex(of: viewController) else {
        return nil
    }
    return page(at: index + 1)
}
    
func page(at index: Int) -> UIViewController? {
    guard index > 0 else {
        return views.last
    }
    guard index < views.count else {
        return views.first
    }
    return views[index]
}


Таким образом мы получаем зацикленный календарь который можно вечно переворачивать и видеть снова 3 сентября.

Полный листинг кода
import UIKit
import SwiftUI

struct CalendarView: View {
    var body: some View {
        ZStack {
            VStack {
                ZStack {
                    Text("Сентябрь")
                        .foregroundColor(.red)
                        .bold()
                        .font(.system(.body))
                }
                Text("3")
                    .font(.largeTitle)
            }
        }
        .overlay(
            RoundedRectangle(cornerRadius: 20)
                .stroke(.black, lineWidth: 0.5)
                .frame(width: 100, height: 100)
        )
    }
}

class ViewController: UIViewController, UIPageViewControllerDataSource {
    
    lazy var pageViewController = UIPageViewController(
        transitionStyle: .pageCurl,
        navigationOrientation: .vertical
    )

    lazy var views: [UIViewController] = [
        UIHostingController(rootView: CalendarView()),
        UIHostingController(rootView: CalendarView()),
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        pageViewController.dataSource = self
        
        addChild(pageViewController)
        view.addSubview(pageViewController.view)
        pageViewController.setViewControllers([views.first!], direction: .forward, animated: false)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
    {
        guard let index = views.firstIndex(of: viewController) else {
            return nil
        }
        return  page(at: index - 1)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController,
                            viewControllerAfter viewController: UIViewController) -> UIViewController?
    {
        guard let index = views.firstIndex(of: viewController) else {
            return nil
        }
        return page(at: index + 1)
    }
    
    func page(at index: Int) -> UIViewController? {
        guard index > 0 else {
            return views.last
        }
        guard index < views.count else {
            return views.first
        }
        return views[index]
    }
}

Комментарии (3)


  1. Ivnika
    02.09.2023 20:12
    +4

    Ведете сайт о андроид разработке, здесь пишет о свифте, да еще с упоминанием изрядно надоевшей шутки про 3 сентября, что может пойти не так? :)


  1. FreeNickname
    02.09.2023 20:12

    У меня множество вопросов, которые я не буду задавать, и один, который задам: а зачем Text("Сентябрь") лежит в ZStack?)


    1. Azon Автор
      02.09.2023 20:12
      +1

      Был нужен для красной подложки в верхней части как на MacOS, но подложку убрал а стек не убрал. Можно смело удалять