Tag Archives: iOS

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.

iOS Unit Test Examples / Snippets

In this article I will post common iOS Unit testing examples for testing of:

  1. Asynchronous loading of data using REST API
  2. Loading of a UIView
  3. Method call after UITableViewCell is clicked
  4. Static UITableView sections have correct number of rows
  5. Loading of a UIView from UIStoryboard
  6. IBOutlet connection
  7. Model logic
  8. UITableViewCell subclass
  9. IBAction / Method is implemented
  10. Testing bundle name

Asynchronous loading of data using REST API

Here [RSHTTPClient sharedClient] is an instance of AFHTTPSessionManager subclass. But it doesn’t matter, the main is the principle.

Loading of a UIView

Method call after UITableViewCell is clicked

Here we verify that method restoreHomeKitClicked is called when user selects a specific row in UITableView.

Static UITableView sections have correct number of rows

Loading of a UIView from UIStoryboard

IBOutlet connection

Model logic

Here we test that an array, that is formed inside our model has correct number of items. Model logic testing obviously can be different depending of logic itself.

UITableViewCell subclass

IBAction / Method is implemented

Testing bundle name

The last is a rare case, but helps to prevent someone changing a bundle name of project accidentally.

How to create semi-transparent outside border for UIImageView

Just in case if somebody looks for an UIImage with transparent outside border. If you simply set a layer border, you will get a transparent border, but you will see inside image behind that border, not outside image. I managed to create an ImageView with transparent outside border.

It looks like this:
cool image

The idea is simple. I save UIImage from UIImageView. Then I remove UIImage and set initial layer as border layer. Then I put a new smaller sublayer above it and set a saved UIImage as contents of it.

The same approach can be used for UIButton or UIView.

Что нового в iOS 9

Новинки в iOS 9:

1. Новое встроенное приложение News, улучшения Notes, Maps, Wallet, CarPlay.

2. На iPad появится Split View, можно будет пользоваться несколькими приложениями одновременно, например, Safari и Twitter.

3. Siri станет умнее. Например, можно будет попросить Siri напомнить о чем-то, когда ты будешь дома. Она сама создает уведомление с привязкой к локализации.

4. Улучшения производительности. Батарея на 1 час дольше будет держаться. Встроенные приложения начнут использовать Metal, то есть по сути графический процессор. Для обновления системы достаточно будет не 4, а 1 гб свободной памяти.

http://www.apple.com/ios/ios9-preview/

#iOS9, #Apple

iOS : Creating Random E-mail and Phone Number

roulette_lg

This is a sample code how to create random e-mail and phone number. I used it in my unit tests of authorization.

Solution for iOS Developer Technical Interview Problem

I have found an interesting iOS Developer Technical Interview Problem and solved it.

“I also have the ultimate iOS Developer technical test you can assign a potential hire. It should take 1-3 hours. It is easy to communicate, allows a lot of freedom of implementation so you can really get a better picture into how a developer thinks, and will make sure this developer knows the absolute fundamentals. Ready for it?

Calculate the and display each Fibonacci number from 1 -> max N possible on an iPhone with unsigned integers, and display each F(n) in a table view. The UITableView scrolling MUST remain smooth.

That’s it. You’ll be amazed at how profoundly simple this task sounds and yet how much iOS knowledge can be demonstrated. Not just what they know, but how they structure their work. You can assess their APIs, their separation of concerns when designing classes, the considerations they’ve made for performance, and their knowledge of concurrency. (Not to mention their knowledge of recursive functions.) It is ok to give them the formula, and allow them to use Google. F(n) = F(n-1) + F(n-2).”

This is the result:
IMG_0051

GitHub repository with a solution is here.

I used recursion and concurrency. I added a little delay of 0.1 s to make a delay visible but scrolling is still smooth. This is my solution:

It scrolls without lags on iPhone 6 Plus. I do not calculate twice a fibonacci number if already have calculated it, I store a new fibonacci number in a NSMutableArray.

Using dispatch group to wait until multiple operations executed – including completion block (AFNetworking)

Sorting objects in Objective-C in Alphabet Order by Name

It is a very easy but a common task. There is no need to create any custom NSSortDescriptors. Let’s say, we have an unsorted array of RRRegion objects, that have a name property. This is how we can sort this array:

Краткое введение в push-уведомления на iOS

Иногда нужно сообщить пользователю мобильного приложения о каком-то интересном событии. Таким событием может быть появление нового сообщения для пользователя. При этом, если приложение будет постоянно висеть в фоне и проверять периодически сервер, то это будет крайне неэкономно с точки зрения заряда батареи. Поэтому и придумали push – уведомления. Это сообщения от сервера, которые приходят на телефон пользователя, даже когда приложение не запущено. Отправлять их должен ваш сервер, но не напрямую на телефоны всех пользователей, а через специальные сервера Apple, которые называются APNS – Apple Push Notification Servers. Работают они так:

Push-Overview-467x500

Что нужно, чтобы отправить push – уведомление с сервера на APNS?

  1. Сертификат и ключ к сертификату для данного приложения. iOS-разработчик может их предоставить. См. туториал ниже по их генерации.
  2. Токен устройства. Это хеш-код, который идентифицирует данное устройство в связке с приложением на APNS. Токены нужно собирать в отдельную таблицу на вашем сервере. Для этого необходимо разработать API запрос, по которому iOS-разработчик сможет отправлять на сервер связку токен устройства – имя пользователя или просто токен устройства. Токен может отправляться на ваш сервер при каждом запуске приложения. При получении на сервере соответствующую запись нужно обновлять.
  3. JSON с описанием уведомления. Зная токен для данного пользователя и имея сертификат, можно сформировать JSON специального вида, содержащий текст уведомления и отправить его по SSL на APNS. APNS дальше уже отсылает уведомление на телефон. Имея токены, можно разрабатывать и отправлять с сервера любые push – уведомления, которые потребуются. Для Python уже есть готовые библиотеки для отправки push – уведомлений. Я полагаю, что для PHP, они наверняка тоже есть, так что тут лучше с нуля код полностью не писать и не тратить силы.

JSON может иметь разную конфигурацию в зависимости от ваших потребностей. Полное описание смотрите в документации. Ссылка ниже.

Пример JSON:

Другой вариант:

Здесь badge – это номер, который появится на иконке приложения после прихода уведомления. Он может быть равен например числу новых сообщения для пользователя.
body – текст уведомления

Подробнее:

Apple Push Notification Service

Tutorial

Написал ТЗ для нашего серверного разработчика на работе и решил перенести часть его сюда, так как ТЗ большей частью представляет из себя популярное изложение того, что такое push-уведомления и как их создавать на сервере.

Немаловажный аспект: push-уведомления являются бесплатным сервисом от Apple, то есть за эксплуатацию APNS платить не надо. Вся стоимость их поддержки – это стоимость поддержки вашего сервера. Но даже так, они могут оказаться дорогим удовольствием, особенно если вы платите за мощности в облаке. Также стоит еще раз сказать, что для отправки push-уведомлений необходим SSL, который не все облачные сервисы предоставляют бесплатно.

The best way to create Forms in iOS

I think the best way to create forms in iOS is by using FXForms open-source project. It can be found in Github. There are some alternatives, but only FXForms support iOS 6. However, FXForms is still not flexible enough. So, if you want to create something completely custom by design, probably, it will not be a suitable solution.

The main advantage of this approach is that your forms become very compact. Also you will save tons of time and your nerves creating many similar and boring forms after you understand how to use FXForms. But not so easy. The main difficulty is to learn how to declare fields.

There are many examples in the project repository. This is not a tutorial, but rather an introduction. Basically what you do is you inherit from FXFormViewController to create a form view controller.

And you create a form object inheriting NSObject, that conforms to FXForm protocol.

Header file:

Implementation file:

And this is how you stick FormViewController with it’s Form: