Tag Archives: iOS

Краткое введение в 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:

iOS State Restoration vs NSCoding

My goal was to create a mechanism to store user interface state in my app. So I decided to study Apple’s State Preservation and Restoration, that was first introduced in iOS 6. As far, as I could understand on my own experience use:
1. iOS State Preservation and Restoration, if you want to store navigation state in an app, that doesn’t change root controller of a window at some moment. It is convenient in this case.
2. NSCoding Protocol for simpler tasks, when you don’t want to navigate, but want to save interface states for only several forms, because it is much more flexible – you completely control the process.

I have tried to implement State Preservation and Restoration that was introduced in iOS 6 in my app but unfortunately I failed. The problem was that it’s mechanism is not flexible enough. It can restore state of View Controllers in a linear tree. But if your app as mine changes a Root Controller of your Window at some moment after user logins, for instance, this mechanism will not work. However, in other apps with simpler architecture it can be successfully used. It helps to bring a user right to the place where he stopped using your app last time even if app is removed from the background.

There is a good presentation on this topic on SlideShare.

I used this tutorial also. There is a code on GitHub, that works.

However, there is a good flexible alternative: saving objects to text files using NSCoding protocol:

How to create UIButton that looks like UITableViewCell with AccessoryIndicator

Sometimes you need to create only one button, that looks like a UITableViewCell with accessory indicator. Users are familiar with this control and they know that if they click it, something should appear. For example, it can be used in different forms to select something after user taps a button. Using a UITableView with one section and cell is too complex approach if you need only one such button. Even if you need some more such buttons, you can use this solution to make code a little simpler.

I created an instance of UIButton and reached this goal after some search in StackOverflow and my own attempts. Finally, my button looks like this:
DKAccessoryButton

Yes, it is a UIButton, not UITableViewCell. So, how I did it?

You can look at my repository on GitHub, I have published a source code of such button under MIT Licence Terms.
DKAccessoryButton: https://github.com/wzbozon/DKAccessoryButton

How to build Libetpan for iOS

1. Install Autoconf, Aclocal, Libtool using these instructions. Install XCode Command Line Tools (in Download section of Organizer)
2. Run this in Terminal.
libetpan/build-mac $sh update.sh
3. Try to open Libetpan project for Mac OS X and iOS, select target for iOS and build for Simulator.
4. If any *.a file is not found, build and copy it from iOSPorts for instance. (I had problems with libetpan/build-mac/libsasl-ios/lib/libsasl2.a: No such file or directory)
5. Go here in Finder
~/Library/Developer/Xcode/DerivedData/
6. Open something like
Libetpan/Build/Products/Debug
7. Copy this, it is your library for Intel 64bit based Simulator.
8. If this library works for you (for instance, in MailCore), create .a files for your device (another processor architecture).

How to export a file to iPhone documents folder programmatically

Here I give an example of how to export a file to iPhone documents folder programmatically. I spent a lot of time on managing of how to do it. My main problem was that I couldn’t find documents folder of iPhone simulator. I couldn’t write anything to file and I used a wrong way with NSData class. Finally, I found a recipe in Internet and modified it a little bit.

So look at the example:

This is just a method. Firstly, we discover a documents Directory of a device. Then we NSLog it in order to find that directory on Mac, if we use iPhone/iPad simulator. Then we make a file name to write the data to using the documents directory. Then create content – four lines of text, including even some non ASCII text(that’ the modification). Then we just save content to the documents directory. Now that file is available through iTunes in programs tab, in the bottom of it for the given Applicaton. Note that you should add “Application supports iTunes file sharing” line and check it in your Info.plist file for your application in order to be able to use iTunes/iPhone/Programs/Your app to share files. Also note that encoding:NSUTF8StringEncoding is needed if you want to use non ASCII letters.

[crayon-66061491b0238842839438/]

SQLite on Mac OS X examples

Here I decided to write some SQLite(SQLite on wiki) on Mac OS X examples of code for creation of database and database management.

1. Go to the folder where you want to create SQLite database (all this is written on Applications/Services/Terminal):

cd /Users/user/Documents/

2. Create database:

sqlite3 SimpleVocabulary.sql

3. Create table in that database:

CREATE TABLE Cards(CardID VARCHAR(5) PRIMARY KEY, Word VARCHAR(1000), Translation VARCHAR(3000), MemoStatus VARCHAR(1));

4. Insert values to the table:

INSERT INTO Cards VALUES ("1", "Mother", "Mama", "Y");

5. Select values from table:

SELECT * FROM Cards;

Another code examples:

1. cd /Users/user/Documents/
2. sqlite3 TexDatabase.sql
1.SELECT * FROM Lessons;
2.SELECT COUNT(*) FROM Lessons;
3.DELETE FROM Lessons;
4.CREATE TABLE Lessons(LessonID VARCHAR(5) PRIMARY KEY, LessonGroup VARCHAR(5), LessonTopic VARCHAR(100), LessonText VARCHAR(20000), LessonCode VARCHAR(100), LessonPicture VARCHAR(100));
5.Drop table Lessons;
6..schema

Here .schema command allows you to look at your tables structure.

Another example:
1. cd /Users/user/Desktop/Alwawee/AlwaweeApps/Бизнес-цитаты/Database
2. sqlite3 BusCitDatabase.sql
3. sqlite> CREATE TABLE BusCits(ID VARCHAR(5) PRIMARY KEY, Text VARCHAR(3000), Author VARCHAR(500));
4. sqlite> .quit
5. SELECT COUNT(*) FROM BusCits;
6. SELECT COUNT(*) FROM BusAuthors;
7. sqlite> CREATE TABLE BusAuthors(AuthorID VARCHAR(5) PRIMARY KEY, AuthorName VARCHAR(100), AuthorInfo VARCHAR(3000));
8. SELECT COUNT(*) FROM BusAuthors;
9. DELETE FROM BusAuthors;
10. DELETE FROM BusCits;
11. SELECT DISTINCT Author FROM BusCits WHERE Author NOT IN(SELECT AuthorName FROM BusAuthors);
12. cd /Users/user/Documents/
13. cd SimpVoc
14. sqlite3 TransWords.sql
15. INSERT INTO Cards VALUES ("1", "Mother", "Madre", "Y");
16. INSERT INTO Cards VALUES ("2", "Example", "Ejemplo", "Y");
17. INSERT INTO Cards VALUES ("3", "World", "Mundo", "Y");
18. SELECT * FROM Cards;

Here .quit command quits sqlite> mode on your Terminal.