Обновить
8
Егор Олегович@cbepxbeo

Разработчик

35
Подписчики
Отправить сообщение

Спасибо, я понимаю о чем Вы, мне сейчас тоже больно читать свое творение. Но оно, есть в том виде, в котором я его создал и править я его не буду. В какой-нибудь новой статье, да, это будет уместно, редактировать существующее - нарциссизм как по мне. В остальном согласен на 70-80%, код стаил конечно классная история, но разработка как правило, история про бизнес, а не про код. А бизнес предпочитает финансы и сроки. Отсюда небольшой тезис. Работающий код - не всегда красив, а красивый код - не всегда работает.

Ну мозг штука странная. Монеткой не сравнивал, я фотографировал. Результат то понятен, размер один. А вот восприятие, как бы я не старался - разное. Причем, что интересно - есть четкое ощущение того, что и детализация разная (я понимаю, что это не так, но ощущение есть). Полагаю эффект связан не сколько с объектами вокруг, а с влиянием атмосферы + разные длины волн.

Никакого, моя проф деформация и косяк, спасибо за подсказку, перечитал публикацию, действительно стиль оставляет желать лучшего. В оправдание могу сказать, что очень увлекся и проигнорировал этот момент. В будущем учту это.

Спасибо, все по факту. Обязательно учту замечания в будущем.

Примерно так и работает свифтюай

Спасибо, я достаточно осведомлен о том как работает SwiftUI.

Вас, я так понимаю, ни капельки не смутило, что опционал опционала влез? Хотя условие было, что это должно быть вью.

А чем меня, простите, это должно смутить? Какое такое условие? Вы определяете входящий тип и обязываете его соответствовать протоколу View. Optional ему соответствует. В документации об этом указано. И что же не так? Вполне ожидаемое поведение.

В этом же и есть суть проблемы.

Да какой проблемы? Серьезно. Я либо Вас не понял, либо просто что-либо еще не понимаю. Изначально (согласно публикации, которую мы сейчас комментируем), была проблема в том, что из-за Helper'а, появился якобы баг, хотя по факту, просто в инициализаторе забыли поставить «?».

Ну Вы сами логически подумайте, вот просто по порядку.

  1. Есть инициализатор, который принимает два неопциональных значения и инициализатор, который принимает одно значение, задавая второе самостоятельно.

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

  3. Появляется Helper, который всегда использует первый инициализатор, просто передавая ему nil, в случаее отсутствия значения (опустим, что Helper иначе можно было построить или добавить еще один инициализатор, готовый к такому сюжету).

  4. Инициализатор построен на дженериках и принимает любой тип, который соответствуют View, следовательно пропускает опционал, при этом в инициализаторе не указано, что параметр опционального типа т.е. nil там точно не будет.

  5. В представлении идет проверка на nil

Беря во внимание вышеизложенное, мы получаем опциональное свойство в представлении, проверку на эту опциональность (отображение, цвет) и инициализатор, который никогда не присвоит nil свойству. Ну очевидно же. Просто правим инициализатор.

С этим вроде разобрались. Идем дальше. Вы негодуете из-за того, что .some(nil) не проходит проверку на nil (опустим, что Optional это перечисление, где в some должен быть тип, а под опционал предусмотренно .none, и пихать в .some nil, уже неправильно). Я Вам пишу, что .some(nil) не соответствует nil т.к. это вообще разные вещи и nil не равно Optional(nil). Что же не так? Я правда силюсь понять, что конкретно в этой ситуации идет не по плану. Смею предположить, что негодование связано с тем, что нельзя проверить на nil Optional(nil).

Так можно, кто сказал что нельзя. В интеренете решения нет? Ну так это ни о чем и не говорит, от Apple прямых упоминаний об этом нет, а там далеко не дураки сидят, значит решение есть. Новый вопрос - это решит «проблему»? Ну давайте тогда подумаем логически, как можно это организовать.

App, принимает в body протокол View (о структуре не слова, именно протокол), какой протокол поддерживают все классы? AnyObject. Причем тут классы и протокол AnyObject? Мы не работаем со структурами во SwiftUI, а работаем с протоколом View, а протоколу View могут соответствовать как структуры так и классы, следовательно возможно приведение к AnyObject. Логично? Что даст на выходе null при преобразовании в AnyObject? nil, Optional(nil) и т.д. Как мы можем работать с null в Swift? С помощью NSNull. Вот Вам и готовое решение.

extension Optional where Wrapped: View {
    var isNil: Bool {
        if ((self as AnyObject) as? NSNull) == nil {
            return false
        } else {
            return true
        }
    }
}

...//код

// базовый конструктор
init(title: T1, description: T2?) {
	self.title = title
	self.description = description.isNil ? nil : description
}

...//код

Я проверил, работает ожидаемо

К слову, я не утверждаю, что это какое-то там хорошее решение, просто первое, что мне пришло в голову и склоняюсь к тому, что просто проектировать надо иначе. Говорю не с пустого места т.к. написал не одну сотню представлений и нигде таких проблем у меня не возникало, опять же это не означает, что я вот делаю правильно, а все остальные неправильно. Просто есть документация Apple, есть правила, примеры и возможности. Надо брать все это во внимание.

И как я уже писал ранее, проблемы все же нет, все вот это, притянуто за уши.

чет слишком сложно для новичков

Да вроде нет, итак максимально простым сделал, проще мне кажется некуда, но конечно это субъективно. Если Вам не сложно, был бы благодарен, если Вы укажете более детально, что мною изложено не достаточно понятно. Я учту это в будущем.

надо было назвать не "Классы и структуры", а "Как инициализировать классы"

Не согласен с Вами. Инициализация, расширения, классы и структуры конечно же являются разными темами, но т.к. инициализатор является неотъемлимой частью класса/структуры, я был обязан осветить этот крайне важный момент.

На моменте с сетевым кодом я уже потерял нить повествования

Его можно пропустить т.к. это пример, но так же спасибо за замечание, в будущем постораюсь развивать повествование и подачу информации.

Какой великий смысл был в typealias?

Демонстрация его использования не более, просто выбрал наиболее удачное место в публикации (на мой взгляд конечно).

К чему было предисловие с функциями в первой статье

Чтобы от них перейти к методам т.к. расчет на ознакомление. Человеку, который небыл знаком с ОПП, подобное может быть непонятно.

Зачем столько танцев с инициализаторами

Наверное при ответе на этот вопрос, мне стоит начать с другого вопроса - «какую цель я себе поставил в момент создания публикации?». Собственно цель иначально проста, доступно объяснить, что такое класс и структура, а так же чем они отличаются. Попутно прицепить какие-либо моменты, чтобы они были понятны и смотрелись уместно. Исходя из этой цели, я не могу ей удовлетворить, не описав инициализаторы т.к. если просто напишу «У структуры есть почленный инициализатор, а у класса нет» это будет не объяснением, а ерундой. Грубо говоря, чтобы понять отличия, надо знать возможности, поэтому я так все и расписывал.

P/s. Я вообще считаю публикацию очень бедной, столько еще всего можно рассказать, но я ограничился текущим вариантом, возможно немного переборщил. Ну и конечно спасибо за вопросы и замечания.

Если Вы читали публикацию не ознакомления с ней ради, а в целях обучения, то можете задать любой интересующий Вас вопрос, я постораюсь ответить более ёмко и понятно.

Если Вы прочитаете публикации более внимательно, то там есть много упоминаний одной особенности, которая присуща им. Это обучающий материал для понимания общих концепций языка, рассчитаный на новичков. Просто примеры кода и пояснения. Насколько смог не обладая педагогическим образованием подать попроще, настолько и подал. Соответственно ни о каком стиле написания кода не может быть и речи. Ну и конечно, если Вас что-либо не устраивает то Вы можете просто не читать раз я такой плохой автор)

P/s. К чему этот комментарий, я не понял. Если есть что добавить по материалу, здорово, пишите, спасибо Вам скажу. Сейчас же это выглядит как хейт.

Так Вы в итоге, используя код

let v: Optional<Optional<Text>> = .some(nil)

UltraView(
	title: Text("чук рулит"),
	description: v)

передаете не nil, а nil завернутый в опционал (Optional(nil)), так что код работает именно так как задумано т.к. nil не равен Optional(nil).

Что Вас удивляет касательно Optional? Идем в документацию - ссылка

прямым текстом указано, что Optional соответствует View.

Я согласен, что сама возможность такой ситуации является проблемой, но это не проблема языка, а проблема проектирования. Решение очевидное, использовать другой подход в построении.

P/s

Я пытался понять, зачем использовать код из примера, но так и не придумал ситуацию, где может понадобиться подобная реализация.

Проверил. Поведение соответствует ожиданию (с исправленным инициализатором).

Вы не пропустили, я просто не указывал это в публикации.

На примере метода/функции существуют следующие варианты

//Вариант 1
func myFunc(name: String){
	//Внутри используется name
	print(name)
}
//В момент вызова используется name
myFunc(name: "Имя")

//Вариант 2
func myFunc(toName name: String){
	//Внутри используется name
	print(name)
}
//В момент вызова используется toName
myFunc(toName: "Имя")

//Вариант 3 (опускаем указание имени)
func myFunc(_ name: String){
	//Внутри используется name
	print(name)
}
//В момент вызова ничего не используется
myFunc("Имя")

Точно так же подобный подход можно применять и вне методов

//Так как нам не нужно возвращаемое значение, то опускаем
if let _ = error { return }

Это шутка такая? Раздули вы ребята из мухи слона конечно. Я может заблуждаюсь (нет мака под рукой для проверки), но пока я вижу вместо проблемы, очень глупую ошибку и необходимость добавить в инициализатор опционал (в самый первый пример кода). Полагаю это решит проблему.

Вот сюда добавить.

...///код

// базовый конструктор
init(title: T1, description: T2?) {
	self.title = title
	self.description = description
}

...///код

Я обязательно проверю свое умозаключение, но если кто проверит быстрее, отпишите, будьте любезны.

P/s. Под глупой ошибкой я имею ввиду саму ошибку, а не то что автор глупый. Примерно как символ пропустить и сидеть искать.

Да, она (публикация) в процессе. Информации много, времени свободного не очень.

Про дженерики я уже готовлю материал, Вы верно подметили.. но учитывайте, что подача и материал рассчитаны на усвоение т.е. для новичков. Я многое упростил и в целом код весьма простой. А на то, что протоколы вместо дженериков… ну не знаю. Использовать их (дженерики) без связанных типов, которые как раз таки обеспечиваются протоколами, практически не имеет смысла, разве что, при разборке json в модель, а вот польза протоколов даже без дженериков, неоценима. За сим, мое мнение - протоколы, важнее нежели дженерики.

Я в последнее время, в основном, ориентируюсь на Swift, для меня это некий фаворит. Не с позиции слепой любви, много с чем работать приходилось, а вполне себе с мотивацией. Не уверен конечно, что мотивация претендует на звание «адекватной», но для меня ее хватает. Заключается она в следующем.

Компания Apple стоит у истоков компьютеростроения, у них единственных кроме Microsoft есть своя операционная система,а на мобильном поприще так они вообще многих похоронили. Проектируют процессоры, классный софт и т.д.. В общем я к чему это пишу, я полагаю там в обязательном порядке есть крутая команда Uber специалистов в разработке. Язык достаточно новый. Разрабатывала команда далеко не глупых людей. Если уж кто и учел современные тенденции, возможности и т.д. так это Apple в момент разработки языка. Пускай он молодой, но уже обладает и достаточной популярностью и возможностями. Возможности максимально логичные и продуманные. Не без косяков конечно, но это минусы обратной совместимости. Настанет время и Objective-C уйдет в прошлое, а Swift по настоящему раскроется.

Это конечно все демагогия, как уже писал выше сколько людей, столько и мнений. Но мое предпочтение на сегодня Swift и как Вы писали уже, терминология в Swift, по моему внутреннему компасу, отвечает всем требованиям. Было бы время, я бы с удовольствием и с головой погрузился бы в это (исследование), век живи, век учись так сказать, чтобы оперировать какими либо данными, а сейчас это чисто интуитивное ощущение.

Ну как сказать, быстрый поиск дает следующее определение:

Протокол — набор правил, соглашений, сигналов, сообщений и процедур, регламентирующий взаимодействие между сопрягаемыми объектами.

И вот такое определение:

Интерфейс – совокупность аппаратных и программных средств, необходимых для взаимодействия с программой, устройством, функцией.

Я понимаю, что Вы имели ввиду т.к. протоколы в Swift очень похожи на интерфейсы в Java, но все же склонен к тому, что interface менее подходящее определение, нежели protocol. Ну вот чисто логически. Интерфейс... даже само слово не дает мне конкретных ассоциации, я много чего могу себе представить, вплоть до визуальной части. А протокол, он и в Африке протокол. Сразу понятно, что это некая директива и т.д.

Конечно сколько людей, столько и мнений, но я попытался посмотреть на это сбоку. Возможно в Apple руководствовались тем же.

А Вы предисловие, читали перед подобным комментарием? Это код написан за 10 минут в информационных целях как наглядная демонстрация возможностей языка. Для новичков в разработке. Не более. Наглядно, быстро, по факту. Плюс я сам писал, что это костыли. Насколько было можно склеить воедино различные плюшки Swift, настолько я и склеил. Или вы предлагаете обернуть все в протоколы с расширениями, на дженериках и т.д. но тогда это уже будет не учебный материал. Перечитайте, будьте любезны.

Согласен, на беке реализовать будет проще. Но Вы посмотрите на код, это не последовательные запросы, выполняются они асинхронно. Конечно в примере реально костыльный код, он больше для ознакомления, но общую его концепцию можно развить при желании. Можно отлавливать провалившиеся запросы и ставить их в очередь повторной загрузки по определенным критериям, с защитой от бесконечной рекурсии и т.д. Combine работает тоже весьма неплохо. Да и в целом, если поднажать, можно вполне себе годный сетевой слой реализовать, с кэшированием и т.д. вопрос мотивации и необходимости.

Об этом будет во второй части, когда будет о структурах.

Если Вам подобное интересно, то можно и заморочиться.) Но конкретно в этой публикации мои мотивы несколько в другом, я очень радею за популизацию языка в России и Вы же понимаете, что доступной информации очень мало. А для новоиспеченных разработчиков, так и вовсе не найти. Все ограничивается туториалами про различие переменных и констант. В примере я хотел обозначить несколько моментов. Практический пример передачи замыканий, использование didSet, обращение к экземпляру по цепочке, примитивы работы с сетью. Мне кажется получилось не плохо. А вот с предупреждениями конечно прогадал. Когда я готовил материал, мне казалось очевидным, что это далеко не рабочее решение.

Дженерики я не очень жалую если честно, я законченный адепт kiss. Если и реализовываю что-либо, то стараюсь делать это изолировано и под определенные задачи со строго определенным типом. Понятно, что без них не обойтись, но всегда стараюсь свести их количество к минимуму, но это уже мои сугубо личные предпочтения.

Да кто же спорит). Я же специально написал, что это пример реализации для того, чтобы было понятно как и что работает. Вы вероятно не представляете, сколько людей в лоб пользуются решениями/библиотеками и т.д. абсолютно не вникая в происходящее. Для этого и я набросал этот фейкокод. Возможно мало предупреждений добавил, поправлю.

1

Информация

В рейтинге
Не участвует
Откуда
Пенза, Пензенская обл., Россия
Дата рождения
Зарегистрирован
Активность