Як виявити зміну орієнтації?


148

Я використовую Swift, і я хочу мати змогу завантажити UIViewController, коли я повертаюсь до пейзажу, чи може хто-небудь вказати мене в потрібному напрямку?

В Інтернеті я нічого не можу знайти і трохи заплутаний у документації.


1
Я припускаю, що API не змінився, тому він повинен бути "didRotateToOrientation" і "willRotateToOrientation", щось подібне, погляньте на документацію Apple
David 'mArm' Ansermot

1
Привіт @ mArm.ch, дякую за швидку відповідь! То як би я це здійснив? (Це мій перший додаток ... Я дуже новачок у IOS) :)
Девід

Я відповів, як відповідь, для інших людей. Чи можете ви прийняти це, якщо для вас це нормально?
Девід 'mArm' Ansermot

Відповіді:


194

Ось як я працював:

У AppDelegate.swiftвсередині didFinishLaunchingWithOptions функції я ставлю:

NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)

а потім всередині класу AppDelegate я поставив таку функцію:

func rotated() {
    if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
        print("Landscape")
    }

    if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
        print("Portrait")
    }
}

Сподіваюсь, це допомагає комусь іншому!

Дякую!


5
Я спробував додати addObserver в AppDelegate, але продовжував отримувати SIGABRT в CoreFoundation з нерозпізнаним селектором. Однак, коли я перемістив addObserver на viewDidLoad, в першому моєму огляді він працював чудово. Просто для інформації, якщо хтось стикається з тим самим питанням.
FractalDoctor

1
Я новачок в кодуванні, але не повинен selectorмати формат рядка "rotated:"??
Хамелеон

4
Я впевнений, що це лише в тому випадку, якщо ви приймаєте аргументи (що rotated()не відповідає)
Девід,

26
Будьте обережні, тому що UIDeviceOrientationце щось інше UIInterfaceOrientation. Це тому, що ви UIDeviceOrientationтакож виявляєте орієнтації обличчям вниз та обличчям вгору, тобто ваш код може перемикатися між портретом і пейзажем безладно, якщо ваш пристрій опирається на майже рівну, але злегка нерівну поверхню (тобто гойдається на виступаючій поверхні) камера
6/6

4
Цей спосіб НЕ ПРАЦЮЄТЬСЯ, якщо телефон відключив автоматичне обертання.
chengsam

178
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    }
    if UIDevice.current.orientation.isFlat {
        print("Flat")
    } else {
        print("Portrait")
    }
}

71
Це буде називатися ПЕРЕД обертанням. Якщо вам потрібен, наприклад, розмір кадру після обертання, це рішення не працюватиме.
Оновлення

не працював у розширенні. пейзаж або портрет досі друкують «портрет»
TomSawyer

4
Цей спосіб НЕ ПРАЦЮЄТЬСЯ, якщо телефон відключив автоматичне обертання.
chengsam

5
на iPad, оскільки клас розмірів однаковий регулярний як для пейзажу, так і для портрета, цей метод ніколи не називають.
Джекі

Це також не вдасться, якщо пристрій поверне значення isFlat. developer.apple.com/documentation/uikit/uideviceorientation/…
CodeBender

57

Потрібно виявити обертання під час використання камери з AVFoundation, і виявив, що didRotate( тепер застарілі ) та willTransitionметоди були недостовірними для моїх потреб. Використання сповіщення, опублікованого Девідом, спрацювало, але для Swift 3.x / 4.x воно не є актуальним.

Swift 4.2 Ім'я сповіщення було змінено.

Значення закриття залишається таким же, як Swift 4.0:

var didRotate: (Notification) -> Void = { notification in
        switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("Portrait")
        default:
            print("other")
        }
    }

Щоб налаштувати сповіщення для Swift 4.2 :

NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
                                       object: nil,
                                       queue: .main,
                                       using: didRotate)

Щоб зірвати сповіщення для Swift 4.2 :

NotificationCenter.default.removeObserver(self,
                                          name: UIDevice.orientationDidChangeNotification,
                                          object: nil)

Щодо заяви про депресію , мій початковий коментар був оманливим, тому я хотів його оновити. Як зазначалося, використання @objcумовиводу було застарілим, що, в свою чергу, потрібно було використовувати #selector. Використовуючи натомість закриття, цього можна уникнути, і тепер у вас є рішення, яке повинно уникнути аварії через виклик недійсного селектора.

Все, що нижче, застаріло на XCode 10 та iOS 4.2

Swift 4.0 Завдяки Swift 4.0 Apple рекомендує нам уникати використання#selector , тому зараз цей підхід використовує блок завершення. Такий підхід також сумісний із Swift 3.x і був би рекомендованим підходом уперед.

Це попередження компілятора, яке ви отримаєте в проекті Swift 4.x, якщо ви будете використовувати цю #selectorфункцію через депресію @objcвисновку:

введіть тут опис зображення

Вступ в цю швидку еволюцію .

Налаштування зворотного дзвінка:

// If you do not use the notification var in your callback, 
// you can safely replace it with _
    var didRotate: (Notification) -> Void = { notification in
        switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("Portrait")
        default:
            print("other")
        }
    }

Налаштування сповіщення:

NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
                                       object: nil,
                                       queue: .main,
                                       using: didRotate)

Зірвіть його:

NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)

4
Чи маєте ви посилання на те, де Apple говорить про відмову від використання #selector у Swift 4? Я хотів би прочитати, чому вони говорять про це.
jeffjv

@jeffjv Звичайно, у мене немає прямого посилання на документ Apple, але я включив скріншот попередження компілятора, яке надає XCode, якщо використовувати попередній підхід.
CodeBender

1
Я додав посилання на швидку еволюцію, яка обговорює зміни.
CodeBender

1
@CodeBender: Попередження компілятора не означає те, що ви пропонуєте. #selector не амортизується, лише "@objc". Це означає, що при використанні функції як #selector вам потрібно явно позначити її, щоб компілятор генерував додатковий правильний код, оскільки компілятор більше не намагатиметься зробити це з вашого використання. Отже, якщо ви додасте "@obj" у функцію rotate () у своєму рішення Swift 3.0, код скомпілюється без попередження.
Mythlandia

Дякую @Mythlandia, я оновив відповідь, щоб усунути плутанину щодо мого початкового твердження.
CodeBender

19

Використання -orientationвластивості UIDeviceне є коректним (навіть якщо це може працювати в більшості випадків) і може призвести до деяких помилок, наприклад, UIDeviceOrientationврахуйте також орієнтацію пристрою, якщо він знаходиться вгору або вниз, немає прямої пари в UIInterfaceOrientationперерахунку для цих значення.
Крім того, якщо ви заблокуєте додаток у певній орієнтації, UIDevice надасть вам орієнтацію на пристрій, не враховуючи це.
З іншого боку, iOS8 застаріло interfaceOrientationвластивість у UIViewControllerкласі.
Для визначення орієнтації інтерфейсу доступні 2 варіанти:

  • Використовуйте орієнтацію рядка стану
  • Використовуйте класи розмірів на iPhone, якщо вони не переосмислені, вони можуть дати вам зрозуміти поточну орієнтацію інтерфейсу

Що ще не вистачає - це спосіб зрозуміти напрямок зміни орієнтації інтерфейсу, що дуже важливо під час анімації.
На сесії WWDC 2014 "Перегляд прогресу контролера в iOS8" спікер також вирішує цю проблему, використовуючи метод, який замінює -will/DidRotateToInterfaceOrientation.

Ось запропоноване рішення частково реалізовано, більше інформації тут :

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        let orientation = orientationFromTransform(coordinator.targetTransform())
        let oldOrientation = UIApplication.sharedApplication().statusBarOrientation
        myWillRotateToInterfaceOrientation(orientation,duration: duration)
        coordinator.animateAlongsideTransition({ (ctx) in
            self.myWillAnimateRotationToInterfaceOrientation(orientation,
            duration:duration)
            }) { (ctx) in
                self.myDidAnimateFromInterfaceOrientation(oldOrientation)
        }
    }

11

Я знаю, що це питання Swift, але оскільки це одне з найпопулярніших посилань для пошуку в Google і якщо ви шукаєте той самий код у Objective-C:

// add the observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rotated:) name:UIDeviceOrientationDidChangeNotification object:nil];

// remove the observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];

// method signature
- (void)rotated:(NSNotification *)notification {
    // do stuff here
}

11

Легко, це працює в iOS8 та 9 / Swift 2 / Xcode7, просто покладіть цей код у ваш viewcontroller.swift. Він буде друкувати розміри екрана з кожною зміною орієнтації, ви можете замість цього поставити власний код:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
        getScreenSize()
    }
    var screenWidth:CGFloat=0
    var screenHeight:CGFloat=0
    func getScreenSize(){
        screenWidth=UIScreen.mainScreen().bounds.width
        screenHeight=UIScreen.mainScreen().bounds.height
        print("SCREEN RESOLUTION: "+screenWidth.description+" x "+screenHeight.description)
    }

5
Цю функцію було знято, використовуйте "viewWillTransitionToSize: withTransitionCoordinator:" замість
Masa S-AiYa

Окрім застарілого, didRotateFromInterfaceOrientation()він не працює надійно. У ньому відсутні деякі обертання. iewWillTransitionToSize:withTransitionCoordinator:працює добре.
Андрій

@Andrej Багато речей тепер застаріло завдяки Swift 3
Josh


9

Мені подобається перевіряти сповіщення про орієнтацію, оскільки ви можете додати цю функцію в будь-який клас, не потрібно бути представником чи контролером перегляду. Навіть у делегата програми.

SWIFT 5:

    //ask the system to start notifying when interface change
    UIDevice.current.beginGeneratingDeviceOrientationNotifications()
    //add the observer
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(orientationChanged(notification:)),
        name: UIDevice.orientationDidChangeNotification,
        object: nil)

ніж кешування сповіщення

    @objc func orientationChanged(notification : NSNotification) {
        //your code there
    }

8

В Цілі С

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

Швидко

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

Замініть цей метод, щоб виявити зміну орієнтації.


8

Швидкий 3 | Повідомлення UIDeviceOrientationDidChange спостерігається занадто часто

Наступний код друкує "deviceDidRotate" щоразу, коли ваш пристрій змінює орієнтацію в тривимірному просторі - незалежно від зміни з портретної на альбомну орієнтацію. Наприклад, якщо ви тримаєте телефон у вертикальній орієнтації та нахиляєте його вперед та назад - пристрійDidRotate () викликається повторно.

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIDeviceOrientationDidChange, 
        object: nil
    )
}

func deviceDidRotate() {
    print("deviceDidRotate")
}

Щоб вирішити цю проблему, ви можете утримувати попередню орієнтацію пристрою та перевірити, чи не змінюється deviceDidRotate ().

var previousDeviceOrientation: UIDeviceOrientation = UIDevice.current.orientation

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIDeviceOrientationDidChange, 
        object: nil
    )
}

func deviceDidRotate() {
    if UIDevice.current.orientation == previousDeviceOrientation { return }
    previousDeviceOrientation = UIDevice.current.orientation
    print("deviceDidRotate")
}

Або ви можете використовувати інше сповіщення, яке викликається лише тоді, коли пристрій змінюється від пейзажу до портрета. У цьому випадку ви хочете використовувати UIApplicationDidChangeStatusBarOrientationсповіщення.

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIApplicationDidChangeStatusBarOrientation, 
        object: nil
    )
}

func deviceDidRotate() {
    print("deviceDidRotate")
}

6

Повна робоча реалізація способів виявлення зміни орієнтації у Swift 3.0.

Я вирішив використовувати цю реалізацію, тому що орієнтація телефону face upта face downдля мене були важливими, і я хотів, щоб погляд змінився лише після того, як я дізнався, що орієнтація опинилася у вказаному положенні.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //1
        NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

    }

    deinit {
        //3
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
    }

    func deviceOrientationDidChange() {
        //2
        switch UIDevice.current.orientation {
        case .faceDown:
            print("Face down")
        case .faceUp:
            print("Face up")
        case .unknown:
            print("Unknown")
        case .landscapeLeft:
            print("Landscape left")
        case .landscapeRight:
            print("Landscape right")
        case .portrait:
            print("Portrait")
        case .portraitUpsideDown:
            print("Portrait upside down")
        }
    }

}

Важливі деталі, які слід зазначити:

  1. Ви слухаєте потік сповіщень DeviceOrientationDidChange і прив'язуєте його до функції пристроюOrientationDidChange
  2. Потім ви вмикаєте орієнтацію пристрою, обов’язково помічайте, що unknownорієнтація є часом.
  3. Як і будь-яке сповіщення, перед тим, як дезінціалізувати viewController, переконайтеся, що ви перестаєте спостерігати за потоком сповіщень.

Сподіваюся, хтось вважає це корисним.


Дякую, чудово
Мохаммед Разіпур

Тож я розгублений, зараз усі мої погляди підлаштовуються залежно від портретного пейзажу, але це не змінюється, якщо пристрій спрямований вгору? Як би я використав ваш вищевказаний код, щоб досягти такого ж ефекту, коли його обличчя !?
Famic Tech

Чи можете ви дати трохи більше контексту? Я не впевнений, про який ефект ви маєте на увазі. Цей код працює просто для виявлення орієнтації. Якщо ви використовуєте кілька методів виявлення орієнтації, у вас можуть виникнути проблеми.
Роб Норбек

6
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    //swift 3
    getScreenSize()
}


func getScreenSize(){
   let screenWidth = UIScreen.main.bounds.width
   let  screenHeight = UIScreen.main.bounds.height
    print("SCREEN RESOLUTION: \(screenWidth.description) x \(screenHeight.description)")
}

Найясніша відповідь. Працювали для мене.
Дорад

Зараз це застаріло
Азіз Джавед

5

Якщо ви хочете зробити щось ПІСЛЯ обертання завершено, ви можете скористатися таким UIViewControllerTransitionCoordinatorобробником обробки

public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    // Hook in to the rotation animation completion handler
    coordinator.animate(alongsideTransition: nil) { (_) in
        // Updates to your UI...
        self.tableView.reloadData()
    }
}

5

Оскільки iOS 8 - це правильний спосіб зробити це.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    coordinator.animate(alongsideTransition: { context in
        // This is called during the animation
    }, completion: { context in
        // This is called after the rotation is finished. Equal to deprecated `didRotate`
    })
}

4

Перевірте, чи змінився обертання за допомогою: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

За допомогою coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)ви можете перевірити, чи завершено перехід.

Дивіться код нижче:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) in
        // if you want to execute code after transition finished
        print("Transition finished")
    }

    if size.height < size.width {
        // Landscape
        print("Landscape")
    } else {
        // Portrait
        print("Portrait")
    }

}

4

Ось простий спосіб виявити орієнтацію пристрою: ( Swift 3 )

override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
            handleViewRotaion(orientation: toInterfaceOrientation)
        }

    //MARK: - Rotation controls
    func handleViewRotaion(orientation:UIInterfaceOrientation) -> Void {
        switch orientation {
        case .portrait :
            print("portrait view")
            break
        case .portraitUpsideDown :
            print("portraitUpsideDown view")
            break
        case .landscapeLeft :
            print("landscapeLeft view")
            break
        case .landscapeRight :
            print("landscapeRight view")
            break
        case .unknown :
            break
        }
    }

2
willRotateзараз застаріло, краще використовувати viewWillTransition.
до

4

Швидкий 4:

override func viewWillAppear(_ animated: Bool) {
    NotificationCenter.default.addObserver(self, selector: #selector(deviceRotated), name: UIDevice.orientationDidChangeNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
}

@objc func deviceRotated(){
    if UIDevice.current.orientation.isLandscape {
        //Code here
    } else {
        //Code here
    }
}

Дуже багато відповідей не допомагають, коли потрібно виявляти різні контролери перегляду. Цей робить трюк.


Також потрібно перевірити, чи пристрій обертався під час зникнення контролера перегляду (у випадку, якщо інший контролер перегляду відкритий вище за струм). Насправді, ви можете пропустити viewWillDisappearі додати addObserverв viewDidLoad. iOS відписує контролер перегляду автоматично.
Олександр Волков

ви забулиUIDevice.current.orientation.isFlat
user924

3

Мій підхід схожий на те, що показано на bpedit вище, але з фокусом на iOS 9+. Я хотів змінити сферу застосування FSCalendar, коли подання обертається.

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition({ (context) in
        if size.height < size.width {
            self.calendar.setScope(.Week, animated: true)
            self.calendar.appearance.cellShape = .Rectangle
        }
        else {
            self.calendar.appearance.cellShape = .Circle
            self.calendar.setScope(.Month, animated: true)

        }

        }, completion: nil)
}

Це внизу спрацювало, але я почував себе вразливим щодо цього :)

coordinator.animateAlongsideTransition({ (context) in
        if size.height < size.width {
            self.calendar.scope = .Week
            self.calendar.appearance.cellShape = .Rectangle
        }
        }) { (context) in
            if size.height > size.width {
                self.calendar.scope = .Month
                self.calendar.appearance.cellShape = .Circle
            }
    }

2

Я використовую UIUserInterfaceSizeClassдля виявлення зміненої орієнтації в UIViewControllerкласі просто так:

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {

    let isiPadLandscapePortrait = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .regular
    let isiPhonePlustLandscape = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .compact
    let isiPhonePortrait = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .regular
    let isiPhoneLandscape = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .compact

     if isiPhonePortrait {
         // do something...
     }
}

1

Для Swift 3

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        //Landscape
    }
    else if UIDevice.current.orientation.isFlat {
        //isFlat
    }
    else {
        //Portrait
    }
}

ви забулиUIDevice.current.orientation.isFlat
user924

1

Швидкий 5

Клас настройки для отримання сповіщень про зміну орієнтації пристрою:

class MyClass {

    ...

    init (...) {

        ...

        super.init(...)

        // subscribe to device orientation change notifications
        UIDevice.current.beginGeneratingDeviceOrientationNotifications()
        NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)

        ...

    }

    ...

}

Код обробника програми:

@objc extension MyClass {
    func orientationChanged(_ notification: NSNotification) {
        let device = notification.object as! UIDevice
        let deviceOrientation = device.orientation

        switch deviceOrientation {
        case .landscapeLeft:   //do something for landscape left
        case .landscapeRight:  //do something for landscape right
        case .portrait:        //do something for portrait
        case .portraitUpsideDown: //do something for portrait upside-down 
        case .faceDown:        //do something for face down
        case .faceUp:          //do something for face up
        case .unknown:         //handle unknown
        @unknown default:      //handle unknown default
        }
    }
}

0
- (void)viewDidLoad {
  [super viewDidLoad];
  [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}

-(void)OrientationDidChange:(NSNotification*)notification {
  UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];

  if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight) {
    NSLog(@"Landscape");
  } else if(Orientation==UIDeviceOrientationPortrait) {
    NSLog(@"Potrait Mode");
  }
}

ПРИМІТКА. Просто використовуйте цей код для ідентифікації UIViewController, в якій орієнтації


Ваш проект не працює в проекті. чи потрібно мені ще щось робити?
Сид Алі Салман

0
override func viewDidLoad() {
    NotificationCenter.default.addObserver(self, selector: #selector(MyController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
//...
}

@objc
private func rotated() {
    if UIDevice.current.orientation.isLandscape {

    } else if UIDevice.current.orientation.isPortrait {

    }

    //or you can check orientation separately UIDevice.current.orientation
    //portrait, portraitUpsideDown, landscapeLeft, landscapeRight... 

}

0

У iOS 13.1.2 орієнтація завжди повертає 0 до повернення пристрою. Мені потрібно зателефонувати UIDevice.current.beginGeneratingDeviceOrientationNotifications (), щоб отримати фактичне обертання перед тим, як відбудеться будь-яка подія обертання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.