All posts by Admin

Using RACCommand and creating custom RACSignals in Objective C

To bind some action to the button click one can use just a custom RACSignal. But then you have to add three more things in every case:
1. Disable button, while action is performing;
2. Show, that action is in progress;
3. Disable button, if input is incorrect and button should not be able to be tapped.

Instead, if you use RACCommand, you get all these things in a box.

Let’s say, we want to bind RACCommand verifyPhoneCommand to a button. We can create a command in a lazy property in a ViewModel:

Here phoneValidSignal is this signal, that is formed by observing a phone variable:

We pass a RACSignal verifyPhone to the RACCommand to do a job:

This is how we bind a RACCommand to a button:

To track execution of a RACCommand and show an activity indicator we can use executing property:

If errors happen during RACCommand execution we can process those errors:

Asynchronous requests chaining using FlatMap operator in RxSwift

One of the main features of using RxSwift and RxCocoa or FRP is the possibility to chain several asynchronous requests and avoid callback hell. It can be achieved by using FlatMap operator and creating your own Observables from your asynchronous jobs like network requests or heavy calculations. But sometimes it is not simple to understand, how to do it. In this post I would like to show an example from one of my projects. The same can be applied to Objective C + ReactiveCocoa, the idea is the same.

First of all we should create Observables from different asynchronous requests. Then we can chain them using FlatMap operator. My example concerns a classic case – login and profile fetching. In many apps after logging in a user you have to request his profile in a separate request.

Usually you use MVVM with RxSwift. In a ViewModel you can create observables. In my case login() method creates an Observable from Alamofire request. In loadProfile() method Observable is created from ProfileService.

This is how you chain login and loadProfile requests. When they finish, you can do some job with a result profile. In this case I check a trial period and navigate to one of the views depending on a result.

Note that error for both requests is handled in one place using SCLAlertView. FlatMap operator maps a result of a first request to a second request and also flattens Observables. If you use just Map instead of FlatMap, the result of chaining will be an Observable of Observables.

Loading a TableFooterView that uses Autolayout from XIB

You can use Autolayout and Xibs to create a footer view. But you have to put your custom view to the container view, that you assign to tableFooterView. If you use Autolayout and load Header or Footer View from xib, you should add constraints.

Как стать хорошим разработчиком

Полностью согласен с тем, что написано в этой статье.

Чтобы быть хорошим разработчиком нужно:

1. Писать код качественно и быстро. Именно в этом порядке приоритетов. Не работающий, но быстро написанный код не принесет компании хороших результатов. Если не хватает времени – это проблема планирования и менеджмента, а не проблема разработчика.

2. Код должен быть читаемым и простым. Другие разработчики должны в нем легко разбираться. Отсюда следует, что код нужно хорошо комментировать, давать правильные названия сущностям (классам, объектам, методам).

3. Тщательно тестировать свою работу до того, как отдавать ее на тестирование. Лучше самому найти 90% багов и сдать качественный продукт, чем потом вычищать сотни багов, найденные другими людьми в течение нескольких итераций. Нужно избегать переделок.

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

5. Сначала решать проблему, а затем уже начинать писать код.

Some useful features of a CocoaPods podfile

You can specify build settings for all pods or only for one pod. Here is an example:

You can create a podspec for a git repo, that is not a pod. Add this podspec to you project root and make a link for an added pod to specify a podspec. This is a better way to create pods for projects that do not have a pod, than creating a fork with a podspec, since you get latest updates more easily.

Handling Swift JSONDecoder typeMismatch error while using Codable protocol

If you have a problematic JSON, which can contain number or string for some keys, you can decode object without that property and manually set that property after decoding.

For example, I have a Vehicle class inside HistoryItem. In Vehicle model_year can be empty String or non empty Int. Here I am decoding modelYear manually using NSDictionary and trying to get Int. Swift 4 cannot do it automatically.

This is my Vehicle class that is contained inside HistoryItem:

As you see, there is no model_year key in CodingKeys.

Why Swift at least should be faster than Objective C

In sections Optionals and Chaining and Value types there is an answer to a post topic question – Why Swift at least should be faster than Objective C

https://en.wikipedia.org/wiki/Swift_(programming_language)

Using guard has three benefits. While the syntax can act as an if statement, its primary benefit is inferring non-nullability. Where an if statement requires a case, guard assumes the case based on the condition provided. Also, since guard contains no scope, with exception of the else closure, leaseStart is presented as an unwrapped optional to the guard’s super-scope. Lastly, if the guard statement’s test fails, Swift requires the else to exit the current method or loop, ensuring leaseStart never is accessed when nil. This is performed with the keywords return, continue, break, or throw.
ObjC was weakly typed, and allowed any method to be called on any object at any time. If the method call failed, there was a default handler in the runtime that returned nil. That meant that no unwrapping or testing was needed, the equivalent statement in ObjC:

leaseStart = [[[aBuilding tenantList:5] leaseDetails] startDate]

would return nil and this could be tested. However, this also demanded that all method calls be dynamic, which introduces significant overhead. Swift’s use of optionals provides a similar mechanism for testing and dealing with nils, but does so in a way that allows the compiler to use static dispatch because the unwrapping action is called on a defined instance (the wrapper), versus occurring in the runtime dispatch system.

The programmer is free to choose which semantics are more appropriate for each data structure in the application. Larger structures like windows would be defined as classes, allowing them to be passed around as pointers. Smaller structures, like a 2D point, can be defined as structs, which will be pass-by-value and allow direct access to their internal data with no dereference. The performance improvement inherent to the pass-by-value concept is such that Swift uses these types for almost all common data types, including Int and Double, and types normally represented by objects, like String and Array.[41] Using value types can result in significant performance improvements in user applications also.[42]

To ensure that even the largest structs do not cause a performance penalty when they are handed off, Swift uses copy on write so that the objects are copied only if and when the program attempts to change a value in them. This means that the various accessors have what is in effect a pointer to the same data storage, but this takes place far below the level of the language, in the computer’s memory management unit (MMU). So while the data is physically stored as one instance in memory, at the level of the application, these values are separate, and physical separation is enforced by copy on write only if needed.[43]

Creating a cold signal in ReactiveCocoa 7

For any case, there is an arbitrarily complex way to do it.

This prints “HELLO WORLD!”.

AppCode vs XCode

AppCode has features that are not present in Xcode. At a minimum, AppCode will be a good addition to XCode.

The full list of features is here.

Here I will show examples of using AppCode features. Inspired by this article, that was very usefull for me.

1. Quick Fix feature in AppCode is more convenient. Refactoring to Modern Objective C syntax using Quick Fix (Alt + Enter).

Before:

After:

2. Simplifying expressions using Quick Fix.
Before:

After:

3. AppCode can generate code for you. Use Command + N.
Generated code – isEqual and hash methods for a class that has properties – objectID, name, selected:

Description method generated for a class with many properties:

4. Imports do not block other code and are folded. Typos in names are shown and renaming works better than in XCode.
These are small features, but very useful. Here defered should be renamed to deferred.

5. Unused imports and properties are shown.
XCode doesn’t do that.

6. Scroll from source feature in project navigator.
You can open a source file by name as in XCode, but after that you can also navigate to that source file in a project tree in one click.

Updating View With Two Data Sources in iOS

In this article I am going to describe a robust, simple and clean app architecture that allows to update a single iOS tableView from two different data sources asynchronously.

Let’s say, we have two sources of data, that need to be displayed in a tableView. When user pulls to refresh a tableView, two separate asynchronous requests are performed. While updating continues we need to show activity indicator and we can dismiss it only when both requests are finished.

This can be cleanly accomplished using ReactiveCocoa + MVVM. One of the benefits of ReactiveCocoa is in the easiness of synchronization of asynchronous data streams.

One would say, that this task can be also performed by using of dispatch groups. I agree, but it is more complex and not easy to do when the nature of data sources is different. For example, when one of the datasources is HTTP API and the second is a WebSocket.

Architecture looks like this:

In a ViewModel we have 3 arrays – cloudData1 (or any other name you want, that better describes your domain), cloudData2 and a union single datasource of a TableView – tableData. When cloudData1 or cloudData2 updates, the update of tableData is triggered and then it triggers an update of the TableView itself by bindings.

In the init method of a ViewModel we create a binding of cloudData1 and cloudData2 to tableData:

Also we combine two flags of progress cloud1RequestInProgress and cloud2RequestInProgress to a single one – inProgress.

LoadData method of a ViewModel starts the loading of data from each of two datasources:

And in a TableView we create a binding between ViewModels tableData and a View:

Pull to refresh triggers loadData of a ViewModel:

In a view we also create a binding between inProgress property of a ViewModel and the need to dismiss refreshing indicator:

Simple and brief -> easy to support, extend and reuse.