Как стать автором
Обновить
18
0
Александр @SparkLone

iOS

Отправить сообщение
Я в итоге остановился на ForkLift, есть триал, можно затестить.
Голь на выдумку хитра, зачет )

P.S. Да читаем мы теги, читаем )
Спасибо за статью. Отлично все разобрано.
Надеюсь оправдать доверие партии )
Здравствуйте, Святослав )
Времени статьи отняли конечно порядочно, но просто захотелось хоть немного вернуть долг сообществу. Ведь сколько было за эти годы прочитано статей. Есть время разбрасывать камни, и время собирать камни )
Спасибо Вам за ответы.
По поводу вопросов 2 и 3. Для 3ей статьи я как раз создал приложение имеющее идентичный функционал но с разными архитектурными подходами. Производительность правда там особо не померяешь, не те нагрузки. А вот по поводу веса вполне можно было бы сказать, но нужно делать полноценный билд для App Store, там же собирается «по уму», то что не нужно отрезается и все в таком духе.
4) Золотые слова. Я как раз слишком увлекся Rx-фикацией, когда пытался сделать clear Rx везде где только можно. Урок был усвоен )

В последнее время я заинтересовался immutable моделями, судя по WWDC 2016, Apple тоже стала её продвигать. Но тут своих нюансов тоже хватает, как и в Rx. Если в итоге паззл в голове сложится — будет и 3я статья )
Рад, что мои статьи действительно помогают, а не просто осели в избранном )
До юнит тестов у меня руки не дошли (планировал 4й в цикле статей), так что Ваша статья — очень нужна.
К сожалению 3я статья в состоянии «заморозки», она была посвящена архитектурным решениям RxSwift в сравнении с другими (MVC, MVVM без RxSwift). Но в процессе написания пришло понимание, что у меня не хватает времени и опыта практической работы с RxSwift, чтобы написать действительно достойный материал, а писать «чтобы было» не хочется.
В комментариях к другой статье по RxSwift я попробовал попытать автора на интересовавшие меня вопросы, но обьем текста в вопросах стал приближаться к обьему написанной им статьи и общение как то сошло на нет )

Так что сделаю еще одну попытку затронуть интересующие темы, если позволите.
1) Вы, я так понимаю, активно применяете RxSwift в production коде. Это приложения для клиентов или для себя? Если для клиентов — как они смотрят на то, что код будет «нестандартным»?
2) Не сталкивались ли с проседанием производительности в RxSwift?
3) Сколько добавляет в весе использование RxSwift в релизе?
4) RxSwift используется повсеместно во всем приложении или в основном для GUI привязок?

Просто RxSwift подразумевает под собой реализацию парадигмы функционально-реактивного программирования, которая включает в себя неизменяемость, что довольно тяжело выполнить везде. Достаточно посмотреть на их попытку продемонстрировать работу с TableView в RxSwift (TableViewWithEditingCommands).
Так что часто приходится в VM использовать изменяемые модели.
А вообще беда в том, что технология все же еще молода, и нет нормально выкристализованных best practice. Хотя мне очень понравилось работать с RxSwift, так что через время наверное сделаю еще одну попытку.
Не знаю в тему ли будет мой ответ по наушникам, но поделюсь опытом. Очень хорошей звукоизоляцией (именно изоляцией, шумодава в них нет) обладают Beyerdynamic dt 770 pro, поэтому я собственно их и выбрал, это по сути полупроф наушники, часто вижу их на фотках у радиоведущих. Я же работаю дома, рядом дети, и это в плане шумов будет похлеще любого офиса. Действительно спасают, если отвлекает музыка — включается шум дождя и растворяешься в коде (природный шумодав).
Так же огромным преимуществом (для меня так точно) — являются велюровые амбушюры, просто практически у всех наушников со звукоизоляцией используется кожа или что то вроде того, и после часа работы уши оказываются в жаркой бане.
Минусом наверное можно назвать цену, но если смотреть сетап из статьи, лишние 15 тысяч, вроде особой погоды не сыграют.
Правда после покупки они мне прилично давили, на ночь поставил на растяжку и с тех пор никаких проблем.
Ну что тут скажешь, всегда можно найти «Верёвку достаточной длины, чтобы выстрелить себе в ногу» (с)
Ну я поэтому и сказал, что решать только в частном порядке.

Учитывая что идет сравнение по адресу памяти — крайне сомневаюсь, что получится что то сделать. Если бы была такая возможность, — просто представьте какие возможности это открыло бы перед злоумышленниками.
Это бы означало, что все обязаны знать про Rx, я думаю авторы других библиотек не особо обрадуются такому повороту.
Скорее если уж вводить общий API — определить, что если мы подменяем delegate то у прокси обязательно должен быть метод oldDelegate() -> NSObject
И каждая библиотека пусть при подмене делегата смотрит — есть ли такой метод, если есть — рекурсивно получает делегат, и если в итоге понимает что она уже есть где то глубже — ничего не подменять.
Но тут две проблемы.
1) это же надо ввести как стандарт, заставить авторов это реализовать
2) для какой то библиотеки может быть не критично насколько глубоко она стоит в иерархии oldDelegate, а для какой то обязательно надо быть первой. И рано или поздно найдутся библиотеки для которых кровь из носу надо быть первыми. И мы получим ту же проблему.

В общем каждый случай нужно рассматривать отдельно.
Для конкретных двух библиотек решение найти не проблема, вопрос в том как решить в общем виде. Ведь таких библиотек может быть и 20, в каждую вносить знание о каждой — никто не станет даже браться.
Приводить к единому стандарту? Опять таки вряд ли кто займется.
Ну значит я в верном направлении ковыляю.
Жду статью )
С удовольствием почитаю. Статья основанная на успешном опыте будет крайне кстати.
Если вкратце, — MVVM?
Я вот сейчас как раз думаю как по уму это все применить. MVVM, + вынес все таки роутер из ViewController'а. Не очень нравится, что из VM в какой то мере получается god объект, он хоть и делегирует все сервисам, но все таки это уже не совсем чистый VM. Думаю как грамотно распилить VM и стоит ли это делать.
Ну то, что прокси переустанавливается при несоответствии при каждой Rx манипуляции было в принципе освещено в статье в комментариях к содержимому функции proxyForObject
По поводу того баг ли это или нет я затрудняюсь сказать. Точнее понятно, что это потенциальная проблема. Но вот как решить. Можно дать возможность настраивать ядро Rx, чтобы какие то классы и их производные не перезаписывались проксей (в надежде что они уже выставили нашу прокси как свой forwardToDelegate). Не самый лучший подход. Можно кешировать rx_delegate, но тогда нужно следить за временем жизни прокси самому, ну или если после этого сверху что то было навернуто посредством BlocksKit, то наша прокси будет об этом не знать и все будет пролетать мимо BlocksKit. В общем простого решения нет, причем это не проблема Rx, а в принципе библиотек которые вмешиваются в работу runtime'а
Ведь в таком случае баг можно постить и на пресловутый BlocksKit.
Ммм, да вроде в стандартном, RxSwift

RxSwift/RxCocoa/Common/_RXDelegateProxy.m

RxSwift/RxCocoa/Common/_RXObjcRuntime.m

Поиском на гитхабе в репозитории RxSwift находится без проблем

Стоит посмотреть на реализацию в _RXDelegateProxy.m. Если вкратце, — при создании прокси извлекаются все доступные методы и выставляются в качестве доступных. Так же в _RXObjcRuntime.m производится swizzle методов отвечающих за диспетчеризацию.
Таким образом при возникновении события — отрабатывает перехватчик из _RXDelegateProxy

-(void)forwardInvocation:(NSInvocation *)anInvocation {
    if (RX_is_method_signature_void(anInvocation.methodSignature)) {
        NSArray *arguments = RX_extract_arguments(anInvocation);
        [self interceptedSelector:anInvocation.selector withArguments:arguments];
    }
    
    if (self._forwardToDelegate && [self._forwardToDelegate respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:self._forwardToDelegate];
    }
}


Если сигнатура метода есть в нашем списке — вызывается interceptedSelector уже для DelegateProxy

public override func interceptedSelector(selector: Selector, withArguments arguments: [AnyObject]!) {
    subjectsForSelector[selector]?.on(.Next(arguments))
}


subjectsForSelector же заполняется нужными сигнатурами, только когда мы делаем observe для delegate прокси.

public func observe(selector: Selector) -> Observable<[AnyObject]> {
        if hasWiredImplementationForSelector(selector) {
            print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
        }

        if !self.respondsToSelector(selector) {
            rxFatalError("This class doesn't respond to selector \(selector)")
        }
        
        let subject = subjectsForSelector[selector]
        
        if let subject = subject {
            return subject
        }
        else {
            let subject = PublishSubject<[AnyObject]>()
            subjectsForSelector[selector] = subject
            return subject
        }
    }


Таким образом подписываемся мы вроде на все события, но DelegateProxy обрабатывает лишь те на которые есть подписка.

Далее вне зависимости от того отработал код в DelegateProxy или нет — если в _RXDelegateProxy есть forwardToDelegate — событие отправляется уже в оригинальный делегат
Вот как раз над этим сейчас и работаю. Перебираю возможные реализации. Т.к. к сожалению даже в Rx примерах архитектура на мой взгляд говоря не ахти, хоть там и заявлен MVVM, но создавать из ViewController — ViewModel, причем передавая в инициализацию сервисы — так себе идея. Ищу баланс между чистотой кода, расширяемостью и количеством классов на отдельный юнит.
Отлично, большое спасибо )
Хорошо, как смогу сформулировать для себя — опишу свой долгий путь к «идеальной архитектуре» )
Я пока сам определяюсь буду ли использовать и в каком виде Rx в своих приложениях. Надо хотя бы на парочке pet проектов опробовать, потом уже делать выводы.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность