Эта версия фиксирует ошибку компиляции, существующую в XCode 11.1, а также гарантирует, что контроллер представлен в стиле, который передается в.
import SwiftUI
struct ViewControllerHolder {
weak var value: UIViewController?
}
struct ViewControllerKey: EnvironmentKey {
static var defaultValue: ViewControllerHolder {
return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)
}
}
extension EnvironmentValues {
var viewController: UIViewController? {
get { return self[ViewControllerKey.self].value }
set { self[ViewControllerKey.self].value = newValue }
}
}
extension UIViewController {
func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
toPresent.modalPresentationStyle = style
toPresent.rootView = AnyView(
builder()
.environment(\.viewController, toPresent)
)
self.present(toPresent, animated: true, completion: nil)
}
}
Для использования этой версии код неизменен от предыдущей версии.
struct MyView: View {
@Environment(\.viewController) private var viewControllerHolder: UIViewController?
private var viewController: UIViewController? {
self.viewControllerHolder.value
}
var body: some View {
Button(action: {
self.viewController?.present(style: .fullScreen) {
MyView()
}
}) {
Text("Present me!")
}
}
}
Если вы следуете соответствующим соглашениям об именах, сторонние инструменты могут легко интегрироваться с вашей библиотекой и использовать ее. Они будут ожидать getX ()
, isX ()
и т. Д. И попытаются найти их посредством отражения.
Хотя вы говорите, что в настоящее время они не будут отображаться как JavaBeans, я все равно будет следовать условностям. Кто знает, что вы, возможно, захотите сделать в дальнейшем? Или, возможно, на более позднем этапе вы захотите извлечь интерфейс к этому объекту и создать прокси, к которому можно будет получить доступ через другие инструменты?
Я ненавижу эту конвенцию . Было бы здорово, если бы он был заменен настоящим java-инструментом, который предоставлял бы методы доступа / модификатора.
Но я следую этому соглашению во всем моем коде. Мы не программируем в одиночку, и даже если прямо сейчас вся команда согласится на специальное соглашение, вы можете быть уверены, что будущим новичкам или будущей команде, которая будет поддерживать ваш проект, вначале будут тяжелые времена ... Я считаю, что неудобство для get / set не так велико, как неудобство из-за нестандартности.
Я хотел бы поднять еще одно беспокойство: часто программное обеспечение Java использует слишком много средств доступа и модификаторов (get / set). Нам следует гораздо больше применять совет « Скажи, не спрашивай ». Например, замените геттеры на B «настоящим» методом:
class A {
B b;
String c;
void a() {
String c = b.getC();
String d = b.getD();
// algorithm with b, c, d
}
}
by
class A {
B b;
String c;
void a() {
b.a(c); // Class B has the algorithm.
}
}
Этот рефакторинг дает много хороших свойств:
Нарушение соглашения о получении / установке в классах библиотеки Java, безусловно, является ошибкой. Я бы рекомендовал вам следовать соглашению, чтобы избежать сложностей, связанных с пониманием того, почему / когда оно не соблюдается.
Джош Блох фактически поддерживает вас в этом вопросе в Effective Java , где он защищает вариант get
-less для вещей, которые не предназначены для использования в качестве bean-компонентов для удобства чтения. Конечно, не все согласны с Блохом, но это показывает, что есть аргументы за и против сброса get
. (Я думаю, что это легче читать, и поэтому, если YAGNI, отбросьте get
.)
Что касается метода size ()
из структуры коллекций; кажется маловероятным, что это просто «плохое» устаревшее имя, если вы посмотрите, скажем, на более свежий класс Enum
, который имеет name ()
и ordinal ()
. (Что, вероятно, можно объяснить тем, что Блох был одним из двух авторов, приписываемых Enum
. ☺)
Схема get-less используется в таком языке, как scala (и других языках ), с Uniform Access Principle :
Scala сохраняет имена полей и методов в одном пространстве имен, что означает, что мы не можем назвать количество полей, если метод называется count. Многие языки, такие как Java, не имеют этого ограничения, потому что они хранят имена полей и методов в отдельных пространствах имен.
Поскольку Java не предназначена для предоставления UAP для «свойств», лучше всего ссылаться на эти свойства с соглашения о получении / установке.
UAP означает:
Foo.bar
и Foo.bar ()
одинаковы и относятся к свойству чтения или к методу чтения для свойства. Foo.bar = 5
и Foo.bar (5)
одинаковы и относятся к настройке свойства,
Это означает, что для доступа к методу чтения вам нужно будет вызвать Foo.bar ()
, что ничем не отличается от вызова любого другого метода. Примечание: size ()
вместо getSize ()
, вероятно, является устаревшим плохим именованием, сохраненным для Мантра Java - «Обратная совместимость: всегда».
Подумайте об этом: можно указать множеству фреймворков ссылаться на свойство в поле объекта, такое как «имя». Под капотом фреймворк понимает, что сначала нужно превратить «name» в «setName», определить по его единственному параметру, что является возвращаемым типом, а затем сформировать «getName» или «isName».
Если вы не предоставляете такой тип хорошо документированный, разумный механизм доступа / мутатора, ваша структура / библиотека просто не будет работать с большинством других библиотек / платформ.