#ios #swift #class #generics #protocols
#iOS #swift #класс #общие #протоколы
Вопрос:
Я инициализирую свой Glide
класс с помощью a UIViewController
, который соответствует протоколу Glideable
, например:
class Glide : NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate {
private var card: (Glideable amp; UIViewController)?
init(parentViewController: UIViewController, configuration: GlideConfiguration, card: Glideable amp; UIViewController) {}
}
Поэтому, когда вы создаете экземпляр этого класса, вы передаете a UIViewController
, который также соответствует Glideable
протоколу. Теперь я хочу немного изменить это, чтобы, если у вас есть UIViewController
завернутый внутри UINavigationController
такой:
let navCardView = UINavigationController(rootViewController: CardViewController())
затем я инициализирую свой Glide
класс, navCardView
который больше не является просто a UIViewController
, а a UINavigationController
, но я также хочу убедиться, что CardViewController
он соответствует Glideable
протоколу.
Любая помощь в реализации такой архитектуры с использованием Generics будет полезна. Кажется, я не могу понять, как я могу сделать общий тип ограниченным протоколом.
Любая идея будет оценена по достоинству. Спасибо.
Комментарии:
1. Неясно, что здесь означает «инициализировать мой класс Glide с помощью navCardView».
navCardView
не соответствует Glideable, поэтому его нельзя назначитьcard
(и любой код, который работалcard
, не будет применяться). Вы имеете в виду, что хотите передать navCardView в Glide.init и заставить Glide.init извлечь первый ViewController из его стека, сохранить его какcard
, а затем игнорировать остальную часть navCardView? Или вы имеете в виду, что хотите согласовать UINavigationController с Glideable? Или вы имеете в виду что-то другое? (Если последнее, важно, как выглядит протокол.)2. Вы не можете изменить то, что ожидает существующий init in
UINavigationController
. Вы могли бы обернутьUINavigationController
создание экземпляра внутри функции, которая только принимаетGlideable
, или вы могли бы создать подклассUINavigationController
только для работыGlideable
… Но это действительно зависит от того, как вы его используете. Итак, вам нужно рассказать немного больше о том, какова ваша конечная цель.3. Кстати, если
Glideable
всегда используется совместно с UIViewController, лучший способ описать это на уровне протоколаprotocol Glideable: UIViewController
Ответ №1:
Я не уверен, что именно вы пытаетесь сделать, но в целом вы должны использовать enum для представления разнородных типов в swift. Вот как вы можете использовать перечисление для обработки двух случаев: контроллер навигации и отсутствие контроллера навигации, а также сделать класс универсальным для определенного типа контроллера представления:
import SwiftUI
import PlaygroundSupport
import Combine
protocol Glideable { }
typealias GlideableViewController = Glideable amp; UIViewController
final class Glide<SomeGlidableViewController: GlideableViewController>: NSObject, Glideable {
private enum Wrapped {
case viewController(SomeGlidableViewController), navigationContoller(UINavigationController, SomeGlidableViewController)
var glideViewController: SomeGlidableViewController {
switch self {
case let .viewController(viewController): return viewController
case let .navigationContoller(_, viewController): return viewController
}
}
var navigationController: UINavigationController? {
guard case let .navigationContoller(navigationContoller, _) = self else { return nil }
return navigationContoller
}
}
private let wrappedViewController: Wrapped
init(glideableViewController: SomeGlidableViewController) {
wrappedViewController = .viewController(glideableViewController)
super.init()
commonInit()
}
init?(navigationController: UINavigationController) {
guard let glideableViewController = navigationController.topViewController as? SomeGlidableViewController else {
return nil
}
wrappedViewController = .navigationContoller(navigationController, glideableViewController)
super.init()
commonInit()
}
private func commonInit() {
print("This class wraps a VC of type: (SomeGlidableViewController.self)")
print("The wrapped VC is (wrappedViewController.glideViewController)")
if let navigationController = wrappedViewController.navigationController {
print("It is wrapped in a navigation controller")
} else {
print("It is not wrapped in a navigation controller")
}
}
}
Комментарии:
1. Большое спасибо! Код помог мне прояснить некоторые из моих концепций относительно такой ситуации, и теперь я могу справиться с обоими случаями. Большое спасибо! 🙂