Decrypted Kernels As you know, the first beta of iOS 10 came out with kernel cache being decrypted. Initially it was considered as a leak, but Apple confirmed that it was intentional. Time to exlore goodies!
Text handler for iOS 8 (source editor extension). One of the first source editor extensions for Xcode 8 for various simple text manipulations, like URL encoding/decoding, JSON formatting, UIColor to/from HEX. Might be a source for inspiration.
WWDC 2016 Developer Perspective The light of WWDC star is still coming in… Realm has captured a lot of “live sessions” about the most exciting parts from a developer perspective.
Awesome Swift A collaborative edited and well-organized list of awesome Swift libraries. If you search for something something you should definitely try it out.
Swift Algorithm Club Quite a lot of algorithms and data structures for refreshing your memories and/or checking for how to use Swift for those kind of tasks.
GraphQL for mobile Nice review of GraphQL from mobile developer perspective if you wish to know something before (or instead of) digging it by yourself.
That’s my personal favorite news.
There is no information available on how long it has been in work and how long it was tested.
__auto_type
declarations
(source),
it can be used like this:The “fun” thing though is that all those changes (except signing system) require migration to Swift 3.0 (if you’re using Swift, it looks like for Obj-C there are no constraints).
dispatch_assert_queue
and similar can be quite handy. See the whole family.dispatch_barrier_sync
os_unfair_lock
(kind of OSSpinLock
“compatible” with iOS)_NSDictionaryM
combines buffers for 33-50% fewer mallocs sourceCFStringCreateCopy
early-outs for tagged pointers now, which makes
it 4x faster for ~40% of strings sourceNSArray
and CFArrayCreate*
will now return _NSArrayI
and _NSArrayM
instances on iOS/watchOS/tvOS as they have for some time on macOS
sourceCF_IS_OBJC
is way faster (used in bridging) sourceBNNS
basic neural network subroutines moreSFSpeechRecognizer
you can guess what it doesfsync
is available in
the AppStore.
From a user perspective it’s a pretty simple iPhone client for
syncthing. If you never heard about
syncthing
and you ever needed a self-hosted Dropbox you should give
it a try. It’s very nice piece of software, it runs almost anywhere
(Linux, *BSDs, Windows). It’s open source and written in Go so if you
want to practice Go language - you’re welcome to
contribute.
Right now fsync
works in mostly “read-only” mode, i.e. you can view
files, you can delete them, but there is no way to edit. This is gonna
change soon.
From a technical perspective it’s probably one of the earliest iOS applications, which are partially written in Rust.
There is a lot of things to talk about and I hope to provide more technical details in the following posts, while this one covers using Rust as a language for mobile development from my experience.
Being active syncthing
user I was missing opportunity to access my
files from mobile and decided to write an iOS application.
Initially I’ve started writing core code in C, got a first working prototype and understood that I’m spending too much time dealing with managing memory, ownership and so on. I’ve checked available options:
C++ was dropped immediately - I haven’t written in it since university, it changed a lot… and I wouldn’t like to invest my time into it, even if gives more advantages in short-term.
While technically it was possible to use Objective-C, it’s not good
enough for low level stuff and there is a lot of low-level stuff in
syncthing
client.
Swift looked very promising, but it was so immature that even Apple “fanboys” were against choosing it for any serious code.
The problem I saw was that although there is an official Android
client, it’s basically re-packaged syncthing
. Which means it wasn’t
written with mobile in mind, where being memory/traffic/battery
friendly is crucial.
You get were I was heading - I’d be happy to have a cross-platform code written for mobile. And the only option in this case was Rust.
There were moments when I hated Rust - it was a hell of a ride to the API stability. Initially it didn’t feel like a big deal (“ohh, that’s just a couple of changes here and there”). But… Little strokes fell great oaks and a couple of times I was on the edge, considering to rewrite it again in C (or C++ - yep, it’s a huge monster, but it’s also a well known + stable monster).
One of the hidden problems caused by instability was a desire to keep breaking surface as small as possible. Practically it meant ignoring existing libraries and re-inventing half-baked versions just to have a control on when and how to update it.
It was a dark time and I’m glad it’s finally over.
While language and std lib are stable now, there is still a huge necessity in a better documentation. A lot of changes have happened with no announcements and no discussions so if you were always on GitHub, monitoring issues everyday - you’re probably fine. But if you weren’t because you had to write your own code - I bet a lot of that code is already “rusty” and cries for modernization.
At some point I was very disappointed, but I have to admit it was caused mostly by wrong expectations and naive estimations.
As you can see only last 2 reasons are related to the language itself and I hope that at least compilation time will be addressed in upcoming 1.1 or 1.2.
Before Rust I’ve been developing in higher level languages for quite a long time. As a result, there were a lot of things I didn’t even consider - they were hidden, the choice was already made for me. The first impression after using Rust was “ohh, there are so many things I have to decide on my own now!”.
For me personally it was a refreshing experience and also a reminder that there is no way to get performance if you don’t keep it as a primary goal all the time.
Probably more than the language itself I liked the direction it takes in encouraging good engineering practices - you get built-in testing/benchmarking support and a pretty decent documentation generator. Want to go further? Mix them - and you’ll get a bullet-proof documentation, which will fail your tests if you’ve forgot to update it after an API change.
And yet there is also Cargo for
getting repeatable builds out of various dependencies. Std lib was
significantly reduced on the way to 1.0 due to cargo
. What was not
necessary or was controversial was extracted out of tree to a separate
crate1.
That gut feeling of rock-solid foundation becomes even stronger after
familiarizing with Rust’s development process. In short - there is a
bot, which runs tests on approved pull requests and merges into
master
only on success. Sometimes it’s annoying, sometimes it’s
slow, but you’re sure that at any point of time nothing is broken2.
One of the most interesting questions is if there is a place for Rust in iOS development.
In most cases if you’re developing for iOS/OS X - you’d better use Objective-C and/or Swift. They provide much better integration with native frameworks and higher level to work on.
Still, Rust can shine when:
I’d say that the last one is the real bottleneck.
A lot of iOS/OS X frameworks have a pure C interface3, 4 and therefore can be used from Rust directly5. In general it’s easy enough to access Objective C objects either6, but it’s hard to exploit that without loosing portability. So… you can’t move things down to Rust7 - you have to provide smoother interaction between “core” and “UI” by other means.
When Dropbox started cross-platform C++ development, they had the same problem and they solved it8 in Djinni - an automatic binding/proxy generator which bridges native code with cross-platform code. If someone writes a generator for Rust - it can make a huge difference9.
Another way to workaround this problem is to have a pretty isolated
Rust core, which acts as a server and can be accessed through a
well-known protocol. It means there will be additional costs,
definitely higher than automatic data marshaling performed by
Djinni
. Whether it is acceptable or not depends a lot of data flow
in the application.
As a conclusion - unfortunately for mobile cross-platform development Rust is pretty limited nowadays and works good only for specific use cases. A bright side though is that it’s a limitation which can be addressed by tools.
crate is a synonym for a package ↩
unless you’re out of luck and provide by yourself support for a platform which hasn’t official buildbot. ↩
CFFoundation
for example provides access to all native data structures. ↩
Steven Sheldon got into GCD and you can even provide Rust blocks to Objective-C code. ↩
unsafe wrappers can be generated by bindgen, it takes a bit more time to get safe wrappers though. ↩
see examples in rust-objc, rust-objc-foundation from Steven Sheldon and rust-cocoa from Servo. ↩
with the only exception for platform-accelerated APIs. ↩
slides from the talk with more details about goals and motivations. ↩
there is a chance that Dropbox writes generator for Rust as they use it internally, although I doubt it. ↩
As I’ve already mentioned, for me “write-only” mode is not about avoiding ephemeral things (is there anything “real”?) or being disconnected - it’s all about being proactive instead of reactive, this is the only way to concentrate on producing things.
It definitely requires a special environment and I’d say that the most important things are organizing space and time.
By time I literally mean time - it’s impossible to create something you’re proud of without iterating, prototyping, throwing bad attempts, taking time to recover and continue looping.
By organizing space I mean a bit more complex concept. The act of creation is always a path from entropy to a structure, from chaotic bits to organized bits. As your knowledge is what allows you to create, it’s kind of obvious that you should concentrate on converting information to knowledge.
What’s the difference between the two? Connections! It’s all about connections - they form the structure, they form the way you think, what you can think and what you can’t think of.
The thing with connections is that you can see them much easier in “big forms” - no matter what we’re talking about - be it music, be it an idea, be it a life story or anything else.
Tell me how you spent yesterday - I’ll know a couple of facts about you. Tell me about your whole life - I’ll find patterns, I’ll make my conclusions about people in general and your character in particular.
Imho, the most wrong thing about social media and news is that being “small forms”, they just overload you with disconnected bits of information. You can’t use it, but it still occupies (or rather pollutes) your mental space. The space you could use for creating.
That brings an interesting hypothesis: the form of information you consume is much more important than how old and “time-proven” it is (I feel it’s “weird” English, let me know if you have an idea how to reformulate it). You know, it’s always a big surprise what exactly is the last drop for an “Eureka!” moment, but it always is about filling a “last connection” in already highly organized “model”.
One of the reasons why “big forms” are usually much useful is that they require a stronger structure. It means author has to work much harder in both discovering connections and in explaining them to the “reader”.
The simplest lesson I can take from this observation is that “more you write - better you understand”.
This works for other communication channels too - I bet every developer knows how effective rubber duck debugging is. What makes writing so special is that there are no time limits and that helps a lot.
Considering all above, I’ve formulated the following thesises:
After a bit of tinkering, here is a part of my current setup:
The only missing solution so far is IM, to be precise Slack-based work communication. In most cases my response time raised significantly (up to 25 minutes for a reply), but so far that works fine.
I’m practicing this setup a bit less than 2 weeks and so far I have the following observations:
It’s a really inspirational post for me as it resonates a lot with what I’ve though about recently. I can argue a lot of minor details (because “but the great man is he who in the midst of the crowd keeps with perfect sweetness the independence of solitude”), but I can’t agree more with general direction the author takes.
I believe that one of the most limiting factors for current civilization is a culture of consumption. We have too much to consume and our uncontrolled consumption as a result “consumes” our time and available resources, leaving no opportunity to produce and create something.
It’s especially true for developers as we’re overhelmed by available technologies/frameworks/libraries/languages and are interested in trying “one more” shiny, just released thing, which is awesome and just got to HN. I’ve personally done that mistake dosens of times and I’m gonna tell about the recent one in the following posts.
To clarify: it’s not about sticking forever with old tools. It’s about clearing as much space/time as possible for generating new things/thoughts/ideas/products.
I’m not sure I’m ready to formulate it more clearly now, so I’ll start a REPL with my own experiment - instead of limiting myself, I’m going to make sure that I’m in “write only mode”.
What’s the write only mode? It’s the mode where I produce at least as much accessible output as I consume in my expertise areas. Preferably it should be a publicly available output.
The idea here is that it’s actuallly impossible to stop consumption by itself - it’s a dead end, especially in non-expertise areas. But what really makes a difference is what comes out of consumption - my only joy or something others can also use.
]]>Although all changes have been landed to master
, cross-compiled
libraries aren’t distributed with nightly, so in case you’re
interested in trying it out, you can either build it from source
(instructions)
or use a pre-built dist.
As earlier, the main usage sample is located
here. It still uses makefile
based approach and I hope to update for cargo
a little bit later.
Here is the link to feed which is updated once new nightly released.
Once it was complete, I’ve understood that I’d like to see docs for my libraries in Dash as well and here is what I’ve got: rust-docset - it is a Python script which allows to generate Dash docsets and feed from any Rust docs.
It requires a pretty simple TOML manifest to be available, like this one:
and upload.sh
might look like this:
While it started as Rust only project, I believe it could be relatively easily programmed to work with documentation generated by other tools.
]]>About a week ago it was finally merged into Rust master branch which is really great as it is much easier to work on smaller changes now.
Here are instructions on how to build it. So far there is no official iOS buildbot and therefore it might broke at any moment, in this case I recommend to use a original fork which could be considered a “stable” branch, tested to compile and work both on device and simulator. It might lag a bit from the master but not that much.
There is still one issue in LLVM which sometimes crashes compilation process. Patch was submitted but considering previous experience I wouldn’t expect it to be landed in less than a month.
I’ve started work on Arm64 port but it definitely will take much more time considering I have no test device.
]]>In general, all major features are working now, providing first-class support of all Rust safety. There definitely might be small hiccups here and there but I believe they could be solved step-by-step, once the major part will be upstreamed to Rust master branch.
I need some time to clean up the code (as it has a lot of experimenting branches) and once patches to LLVM and compiler-rt landed - the last step will be rebase on current master and issue an PR.
I hope it will be finished this week.
]]>Finally got working Rust cross-compiler for iOS so now it is possible to create static libraries which could be used from Objective C. For now only armv7 architecture is supported (although there are upcoming commits in “try” branch which will update LLVM version with ARM64 support right from Apple).
These were main pain points:
Slow full rebuild… Yep, I know, I know, 3 stage bootstrapping to be extremely optimized but still… it was especially painful on initial stage while experimenting with built options and LLVM patching.
TLS isn’t supported on armv7 so it should be emulated. Initially I’ve started adding it to LLVM and with help from Tim Northover and Dan Olson even got it working. (BTW, Dan knows a lot about this topic as he got a working D compiler for iOS, so if you’re interested in modern compiled language for iOS - you can try it too). Just to discover that actually Rust has built-in TLS “emulation” support (actually using the same technique as in LLVM patches)… Grr, hate myself for not checking this before messing with LLVM.
There were absolutely crazy crashes hard to debug because some kind linker errors/misconfiguration when functions were resolved correctly but all the data was relocated incorrectly and contained garbage.
There were mystical crashes in hash function which automagically disappeared once I’ve increased optimization level.
The final show-stopper was happening in runtime finalization routine - it always crashed on misaligned data during mutex locking. The reason was that mutex opaque data was copied as a plain data. It wasn’t the case on desktop OSes but seemed to be a big difference on iOS. There is a simple fix for native runtime and should be similar fix for green/rustuv.
armv7 only (ARM64 port should be quite easy to introduce)
it is possible to compile standard libraries and use them
“native”-based runtime
creating static libraries which could be used from iOS applications
green/rustuv runtime crashes because of incorrect mutex implementation
segmented stacks aren’t working
it might require additional manual linking
no support for simulator yet
it only works on common compiler flags. It is critical to have exactly –opt-level 2 (or -O) as both decreasing and increasing opt level may cause a lot of unexplainable issues
clone and create build dir
configure
build
or (for 4 core CPU)
There is a sample project with instructions on how to integrate.
Special thanks to Tim Northover (ARM TLS), Dan Olson (ARM TLS), Alex Crichton (Rust internals) and my wife for being patient.
]]>Один из интересных тезисов - это то, что сейчас нас начинает поджимать железо, если раньше мощности росли в количестве гигагерц, то сейчас все идет за счет увеличения числа ядер. А это провоцирует на переход к concurrent-based программированию (есть, кстати, нормальный русский термин для этого?), где императивщина в чистом виде начинает загибаться из-за возрастающей сложности разнообразных локов и защит.
Материал 2007 года и этим вдвойне интересней, т.к. тренды, о которых говорит Джо, из гипотетических становятся все более и более ощутимыми.
]]>единственный аргумент, который может смутить - это types, который
задает типы аргументов и возвращаемого значения в закодированном
текстовом виде. Нужные значения можно посмотреть либо в документации,
либо исппользовать @encode
.
Вторая тонкость оказалась в том, что эта функция добавляет (или переопределяет) метод экземпляра, а что же делать если нужно заменить метод самого класса?
Правильно, получить метакласс с помощью object_getClass(ourClass)
и
заменить его метод как обычно :)
Куб предназначен для замены множества цветов. R, G, B компоненты исходного цвета являются трехмерными координатами нового цвета, который задается в виде 4 float’ов (RGBA).
В приведенном примере происходит хитрая замена цвета со всеми оттенками. Для удобства используется работа с цветом в формате HSV, т.к. в этом случае гораздо легче выцеплять схожие цвета - они будут попадать в сектор.
Представление цвета в HSV:
Итак, на формочке есть 2 слайдера, с помощью которых меняется диапазон заменяемых оттенков. Для удобства считается, что основной цвет для замены находится посередине этого диапазона и именно он меняется на зеленый.
Для этого пробегаем по всем цветам, смотрим попадает ли HSV аналог этого цвета в нужный сектор и если да - запоминаем его смещение относительно центрального. После этого конструируем новый HSV цвет с таким же смещением относительно зеленого и конвертируем обратно в RGB. Подобный код можно было бы использовать, например, для вырезания фона определенного цвета (chroma key). В этом случае все цвета в нужном секторе меняют прозрачность (alpha) на 0.0
Пример заполнения куба:
В действии
Исходное изображение:
Результат замены:
Разница возникает из-за того, что в разных диапазонах берется разный центральный цвет для замены.
Полный код проекта доступен на гитхабе
]]>Поиск не требует вбивания слов целиком.
Позволяет опечатываться (правда не так хорошо, как хотелось бы).
Структура документа висит слева и всегда доступна (не надо возвращаться к началу документа).
Есть возможность работать со сниппетами, но как-то не срослось :-)
Очень радует стабильность и скорость работы.
]]>Дата: 7 декабря Начало: 19.00 Место проведения: Москва, Digital October
Мы традиционно завершаем год встречей в формате блиц-докладов. Приглашаем девелоперов, дизайнеров, менеджеров и всех энтузиастов iOS и Mac OS X. Регистрация на встречу. Участие во встрече как всегда бесплатное.
Ключевые люди российской индустрии расскажут, чем запомнился 2011 год, что было важными событиями и кто были главные люди и какие планы на следующий год. Мы ждем, что Вы также поделитесь с сообществом своим опытом, достижениями и открытиями.
Предновогодняя встреча RADUG – самое правильное место, чтобы оставаться в курсе происходящего, заявить о себе и завязать контакты. После встречи как всегда After Party – планируйте свое время!
Обратите внимание, что в Digital October, перед встречей RADUG пройдет еще одно мероприятие, посвященное мобильной разработке - Mobile Developer Day. Конференция платная, но в ее рамках есть бесплатная секция Developer Garage, включающая два мастер-класса по разработке приложений под iOS. Если есть желание – перед встречей RADUG можно заглянуть также и туда.
]]>Вот как это выглядит:
Пока что iPhone 4 only. Ах да :) Ссылочка
]]>Написана на ruby, установка:
gem install wox
После этого создаем Rakefile, самый навороченный на данный момент пример:
Код в принципе понятен без особых комментариев, настроить можно абсолютно все - сертификаты, какие provisioning profiles использовать, можно даже сразу публиковать на Testflight (о нем писал раньше). Вложенные таски наследуют настройки родителей, т.е. testflight:publish будет собирать с использованием provisioning profile из ipa:adhoc и подписываться это будет сертификатом, указанным в build:release. В случае чего любую настройку можно переопределять.
Примеры использования:
Собрать дебажную версию:
rake build:debug
Подготовить ipa для заливки в AppStore:
rake ipa:appstore
Подготовить adhoc ipa и залить его на Testflight
rake testflight:publish
Посмотреть список всех доступных тасков:
По умолчанию версия продукта берется из Info.plist, но ее можно переопределить с помощью
Последний штрих - генерация правильного changelog’а для Testflight-публикации - остается домашним заданием :)
]]>Установить git-flow на OS X проще простого с помощью homebrew
brew install git-flow
На страничке проекта git-flow Вы можете найти инструкции по установке на Linux и Windows.
Установка git-flow добавляет несколько очень удобных git-команд для создания и управления ветками фич и релизов. Новый git репозиторий создается с веткой master. По умолчанию в git-flow эта ветка используется для production-а. В свою очередь основная разработка происходит в ветке develop. Следует отметить, что git-flow не более чем серия удобных “сокращений” для переключения между этими ветками и перебрасывания изменений из одной в другую. После установки git-flow нужно настроить локальную копию:
git flow init
Вы можете согласиться со значениями по умолчанию, нажимая Enter - это, кроме всего прочего, облегчит настройку git-flow у сотрудников, т.к. им нужно будет использовать точно такие же значения. На самом деле все что, происходит при запуске init - это добавление двух секций [gitflow] в ваш .git/config:
Если вам нужно что-то уточнить воспользуйтесь встроенным хелпом
git flow команда help
Приятное дополнение в виде autocompletion для bash и для zsh
Для старта новой фичи, например feature 77 с вашего issue-tracker’а:
git flow feature start 77-speedup-yak-shaving
Команда создает новую ветку feature/77-speedup-yak-shaving с родителем develop и переключается на нее.
Нужно расшарить работу с другими?
git flow feature publish 77-speedup-yak-shaving
Это одним движением push’ит remote-ветку и привязывает локальную к ней. Стандартные git push и git pull –rebase работают как и должны, т.к. ветки, созданные git-flow, являются обычным ветками и не содержат какой-то специальной информации. Вся хитрость - только в соглашении именования.
Когда фича закончена, ее нужно за-rebase-ить на develop и потом слить:
git flow feature rebase
git flow feature finish 77-speedup-yak-shaving
После этих двух шагов develop будет содержать Вашу новую фичу. Остается только прогнать тесты и за-push-ить.
С релизами управляться очень легко:
git flow release start 2011_year_of_the_yak
Эта команда создает новую ветку release/2011_year_of_the_yak на основе develop. Здесь можно изменить HISTORY или VERSION файлы, закоммитить и выпустить релиз:
git flow release finish 2011_year_of_the_yak
После этого будет создан тег 2011_year_of_the_yak и временная ветка будет удалена. Вы очутитесь в master.
Хотфикс - это feature branch, базирующийся на последнем релизе и который автоматически будет влит и в master, и в develop. Просто и со вкусом.
Модель, по которой работает git-flow: A successful Git branching model
]]>Идея взята отсюда, добавлен один клиент и удалено много копипаста :-)
Если устраивает открытие в Safari - можно откомментировать последний элемент, на этом кастомизация заканчивается.
Вообще поскольку URL в данный момент - это единственный способ для приложений взаимодействовать между собой, рекомендую поглядывать на handleOpenUrl: и подборку схем от Адриана Космачевского
]]>