Social Icons

DevTools

Эта серия сообщений посвящена моей разработке. Инструмент разработчика приложений под iOS.

среда, 26 августа 2015 г.

Design pattern short descriptions from the "Pro Design Pattern in Swift" book

Pro Design Pattern in Swift. Adam Freeman. Apress.

Patterns' short descriptions from the book. Just to remember. The definition quoted (in green color) from the book of GOF.



Creating Patterns

“Creational design patterns abstract the instantiation process.They help make a system independent of how its objects are created,composed, and represented. A class creational pattern uses inheritance vary the class that's instantiated, whereas an object creationalpattern will delegate instantiation to another object.” 
The Object Template Pattern
The object template pattern uses a class or struct to define a template from which objects are created. When an application component requires an object, it calls on the Swift runtime to create it by specifying the name of the template and any runtime initialization data values that are required to configure the object. The benefit of this pattern is that it provides the basic tools that can be used to break tightly coupled components apart, allowing a public API to be presented to the consumers of an object and a hidden private implementation.


The Prototype Pattern

“Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. ”
The prototype pattern creates new objects by copying an existing object, known as the prototype. The main benefit is to hide the code that creates objects from the components that use them; this means that components don’t need to know which class or struct is required to create a new object, don’t need to know the details of initializers, and don’t need to change when subclasses are created and instantiated. This pattern can also be used to avoid repeating expensive initialization each time a new object of a specific type is created. To support cloning, the Foundation framework defines the NSCopying protocol (func copyWithZone(zone: NSZone) -> AnyObject called when the object is copied), which lets you specify how an object should be cloned.

Scope: Object.  Aspect(s) That Can Vary: class of object that is instantiated

The Singleton Pattern

“Ensure a class only has one instance and provide a global point of access to it.



The singleton pattern ensures that only one object of a given type exists in the application.

class var server:BackupServer {
        struct SingletonWrapper {
            static let singleton = BackupServer(name:"MainServer");
        }
        return SingletonWrapper.singleton;
    }

Scope: Object.  Aspect(s) That Can Vary: the sole instance of a class

The Factory Method Pattern

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclass.”
The factory method pattern selects an implementation class to satisfy a calling component’s request without requiring the component to know anything about the implementation classes or the way they relate to one another. This pattern consolidates the logic that decides which implementation class is selected and prevents it from being diffused throughout the application. This also means that calling components rely only on the top-level protocol or base class and do not need any knowledge about the implementation classes or the process by which they are selected.

Scope: Class.  Aspect(s) That Can Vary: subclass of object that is instantiated

Abstract Factory Pattern

“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.”
The abstract factory pattern allows a calling component to create a group of related objects. The pattern hides the details of which classes are used to create the objects and the reason why they were selected from the calling component. This pattern is similar to the factory method pattern. The calling component doesn’t know which classes are used to create the objects or why they were selected, which makes it possible to change the classes that are used without needing to change the components that consume them.

Scope: Object.  Aspect(s) That Can Vary: families of product objects.
  

The Builder Pattern

“Separate the construction of a complex object from its representation so that the same construction process can create different representations.”
The builder pattern puts the logic and default configuration values required to create an object into a builder class. This allows calling components to create objects with minimal configuration data and without needing to know the default values that will be used to create the object. This pattern makes it easier to change the default configuration values used to create an object and to change the class from which instances are created.
The calling component knows what is required—a burger with no ketchup, for example—but it doesn’t know how to create it. The builder class knows how to create a burger and knows the default configuration, but it doesn’t know what the customer wants for any specific order. The builder pattern brings the “what” and the “how” together without letting the calling component become tightly coupled to the objects it requires.
The most commonly used example of the builder pattern can be found in the NSDateComponents class in the Foundation framework.

Scope: Object.  Aspect(s) That Can Vary: how a composite object gets created

The Structural Patterns

“Structural patterns are concerned with how classes and objects are composed to form larger structures.Structural class patterns use inheritance to compose interfaces or implementations.”

The Adapter Pattern

“Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.”
The adapter pattern allows two components with incompatible APIs to work together by introducing an adapter that maps from one component to the other.
This pattern allows you to integrate components for which you cannot modify the source code into your application. This is a common problem when you use a third-party framework or when you are consuming the output from another project.
Scope: Class.  Aspect(s) That Can Vary: interface to an object

The Bridge Pattern

“Decouple an abstraction from its implementation so that the two can vary independently.”
The bridge pattern separates an abstraction from its implementation so that either can be changed without a corresponding change in the other. More commonly, the bridge pattern is used to resolve a problem known as an exploding class hierarchy, which usually arises through repeated but poorly thought-out refactoring and requires
an ever-increasing number of classes to add new features to the application.
When the bridge pattern is applied to the exploding class hierarchy problem, the benefit is that adding a new feature to the application requires only a single class. More broadly, the pattern isolates the impact of a change when an abstraction or its implementation changes.
Use this pattern to resolve the exploding class hierarchy problem or to bridge between one API and another.
The bridge pattern separates an abstraction from its implementation so that the two can be changed independently from one another. It may sound counterintuitive, but the bridge pattern solves the exploding class hierarchy problem by creating two different hierarchies, separating the functionality that is specific to each platform from the functionality that is shared between them. A bridge class is created, which brings together both hierarchies.
Scope: Object.  Aspect(s) That Can Vary: implementation of an object


The Decorator Pattern

“Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.”
The decorator pattern allows the behavior of individual objects to be changed without requiring changes to the classes that are used to create them or the components that consume them.
The changes in behavior defined with the decorator pattern can be combined to create complex effects without needing to create large numbers of subclasses. The decorator solves the permutation problem by creating decorator classes, which are wrappers around the original class that change its behavior. A decorator presents the same API as the wrapped class, and decorators can wrap other decorators in order to create permutations.


Scope: Object.  Aspect(s) That Can Vary: responsibilities of an object without subclassing

The Composite Pattern
“Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.”
The composite pattern allows a tree of individual objects and collections of objects to be treated consistently.
The consistency that the composite pattern brings means that components that operate on the tree structure are simpler and do not need to have knowledge of the different objects types that are in use.
Use this pattern when you have a tree structure that contains leaf nodes and collections of objects.
This pattern is applicable only to tree data structures.
Scope: Object.  Aspect(s) That Can Vary: structure and composition of an object

The Façade Pattern

“Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.”
The façade pattern simplifies the use of complex APIs to perform common tasks.
The complexity required to use an API is consolidated into a single class, which minimizes the impact of changes in the API and simplifies the components that consume the API functionality.
Use the façade pattern when you are working with classes that need to be used together but that don’t have compatible APIs.
Do not use the façade pattern when integrating single components into the application; use the adapter pattern instead.
The façade pattern addresses the problem by creating a class that consolidates the complexity into a single location in the application and presents a simplified API to other components:
Scope: Object.  Aspect(s) That Can Vary: interface to a subsystem

The Flyweight Pattern
“Use sharing to support large numbers of fine-grained objects efficiently.”
The flyweight pattern is applied when a number of similar objects all rely on the same set of data values. Rather than create a new set of data valued for each of the objects, the flyweight pattern shares one set between all of them, minimizing the amount of memory required to store the data and the amount of work required to create them. The flyweight pattern shares common data objects between multiple calling components.
The flyweight pattern reduces the amount of memory needed to create the data objects required by the calling components and the amount of work required to create them. The impact of implementing the pattern increases with the number of calling components that share the data.
Use this pattern when you are able to identify and isolate sets of identical data objects that are used by calling components.
Do not use this pattern if there is no shared data or if the number of shared data objects is small and easy to create.


Scope: Object.  Aspect(s) That Can Vary: storage costs of objects


The Proxy Pattern

“Provide a surrogate or placeholder for another object to control access to it.”
The proxy pattern defines an object—the proxy—that represents some other resource, such as another object or a remote service. Calling components operate on the proxy, which in turn operates on the underlying resource.
Proxies allow close control over the way that the underlying resource is accessed, which is useful when you need to intercept and adapt operations.
Proxies are used in three main situations: to define an interface to a remote resource such as a web page or RESTful service, to manage the execution of expensive operations, and to restrict access to the methods and properties of other objects.

Scope: Object.  Aspect(s) That Can Vary: how an object is accessed; its location


The Behavioral Patterns

“Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects.”

The Chain of Responsibility

“Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.”
The chain of responsibility pattern organizes sequentially a set of objects that may be able to take responsibility for a request from a calling component. The sequence of objects is referred to as a chain, and each object in the chain is asked to take responsibility for the request. The request moves along the chain until one of the objects takes responsibility or the end of the chain is reached.
The chain of responsibility allows objects that can process requests to be ordered into a preferential sequence that can be reordered, extended, or reduced without any impact on the calling component, which has no insight into the objects that comprise the chain.
Use this pattern when there are several objects that can handle a request, only one of which should be used.
The pattern is implemented correctly when the set of objects that can take responsibility for a request are arranged sequentially and each is offered the chance to take responsibility in turn. The individual objects in the chain have no knowledge of one another (other than the next link in the chain).

Scope: Object.  Aspect(s) That Can Vary: object that can fulfill a request

The Command Pattern


“Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.”
The command pattern is used to encapsulate details of how to invoke a method on an object in a way that allows the method to be invoked at a different time or by a different component.
There are lots of situations in which using a command is useful, but the most common ones are supporting undo operations and creating macros.
Use this pattern when you want to allow methods to be invoked by components that otherwise have no information about the object that will be used, the method that will be invoked, or the arguments that will be provided.
Scope: Object.  Aspect(s) That Can Vary: when and how a request is fulfilled


The Mediator Pattern

“Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.”
The mediator pattern simplifies peer-to-peer communication between objects by introducing a mediator object that acts as a communications broker between the objects.
Instead of having to keep track of and communicate with of all of its peers individually, an object just deals with the mediator.
Use this pattern when you are dealing with a group of objects that need to communicate freely between one another. Don’t use this pattern if you have one object that needs to send notifications to a range of disparate objects; use the observer pattern

Scope: Object.  Aspect(s) That Can Vary: how and which objects interact with each other

The Observer Pattern

“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.”
The observer pattern allows one object to register to receive notifications about changes in another object without needing to depend on the implementation of that object.
This pattern simplifies application design by allowing objects that provide notifications to do so in a uniform way without needing to know how those notifications are processed and acted on by the recipients.
Use this pattern whenever one object needs to receive notifications about changes in another object but where the sender of the notifications does not depend on the recipient to complete its work.
Do not use this pattern unless the sender of the notifications is functionally dependent from the recipients, such that the recipients could be removed from the application without preventing the sender from performing its work.

Scope: Object.  Aspect(s) That Can Vary: number of objects that depend on another object; how the dependent objects stay up to date

The Memento Pattern

“Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.”
The memento pattern captures the complete state of an object into a memento that can be used to reset the object at a later date.
The memento pattern allows a complete reset of an object without the need to track and apply individual undo commands.
Use this pattern when there is a “known-good” point in an object’s life that you may want to return to at some point in the future.
This pattern should be used only when you need to return an object to an earlier state.

Scope: Object.  Aspect(s) That Can Vary: what private information is stored outside an object, and when

The Strategy Pattern

“Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.”
The strategy pattern is used to create classes that can be extended without modification, through the application of algorithm objects that conform to a well-defined protocol.
The strategy pattern allows third-party developers to change the behavior of classes without modifying them and can allow low-cost changes to be made in projects that have expensive and lengthy validation procedures for specific classes.
Use this pattern when you need classes that can be extended without being modified.
Scope: Object.  Aspect(s) That Can Vary: an algorithm

The Visitor Pattern

“Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.”
The visitor pattern is similar to the strategy pattern in that it allows the behavior of a class to be extended without modifying its source code or creating a new subclass, except that the visitor pattern is applied to collections of heterogeneous objects.
The visitor pattern allows new algorithms to operate on collections of heterogeneous objects without needing to modify or subclass the collection class.
The visitor pattern is useful when you want to provide collection classes as part of frameworks without requiring third-party developers to modify the source code. This pattern is also useful in projects where modifying core classes triggers expensive testing procedures.
Use this pattern when you have classes that manage collections of mismatched objects and you want to perform operations on them.

Scope: Object.  Aspect(s) That Can Vary: operations that can be applied to object(s) without changing their class(es)

The Template Method Pattern

“Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.”
The template method pattern allows specific steps in an algorithm to be replaced by implementations provided by a third-party, either by specifying functions as closures or by creating a subclass.
This pattern is useful when you are writing frameworks that you want to allow other developers to extend and customize.
Use this pattern to selectively permit steps in any algorithm to be changed without modifying the original class.
Do not use this pattern if the entire algorithm can be changed. See the other patterns in this part of the book for alternatives.

Scope: Class.  Aspect(s) That Can Vary: steps of an algorithm

пятница, 19 июня 2015 г.

Optionals in Swift.

Введение

Считаю, что для тех, кто начал программировать под iOS сразу на языке Swift, минуя Objective-C, трудно понять смысл языковой конструкции Optionals. 
Вот что сказано в документации  [1]: "Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes."
Что это означает. В Objective-C не все типы являются классами. Есть базовые типы, которые не являются классами в терминах ООП.
В Objective-C, если говорят об объектах, то имеют ввиду объкты классов (или инстанс-переменная класса). Так, объявление переменной-указателя на объект выглядит следующим образом:
     UIView* view;
Пока нам известно только одно, что переменная имеет тип UIView. UIView - это класс. Все классы имеют одного общего родителя - класс NSObject. Т.е., все объекты в  Objective-С обладают некими общими свойствами, которые они наследуют от NSObject.  Переменная с именем view хранит адрес в памяти, где находится объект. Пока еще объект не создан. Что это значит? Это значит, что не выдедена память для объекта. Переменная указывает в никуда. Тут возникает вопрос: а что если послать сообщение такой переменной? Ведь не всегда одновременно с объявлением переменной мы инициализируем ее значением, а именно, выделяем память для объекта. К счастью такие переменные инициализируются таким объектом, который ничего не выполняет если ему отправить любое сообщение (вызвать любую функцию у такой переменной). Этот объект -  nil. Транслятор не анализирует, что содержит переменная: nil, ссылку на реально существующий объект, или объект, который уже не существует. В последнем случае программа закрешится. Чтобы этого избежать, надо присвоить переменной nil, если точно известно, что объект уничтожен ранее, или сам факт присвоения nil влечет за собой уничтожение объекта (если переменная владела объектом. Эти ньюансы в данном контексте не важны). В любом случае nil - это такая удобная вещь, которую можно всегда проверить:
    if (view != nil){
...
}  
    или так
    if (view){...
}  
Плюс к тому, что как сказано ранее, вызов метода, например 
    [view setNeedsDisplay];
ни к чему плохому не приведет. По крайней мере программа продолжит выполнение.
Надеюсь теперь это выражение: "Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes."
стало более понятным. 
В Swift есть несколько основных положений. Первое - все является объектом. Даже число 1 - объект (так скажем объект не класса, как можно подумать, а структуры, но сейчас это не важно. Он остается объектом и может принимать сообщения. И классы и структуры - типы. Поэтому можно сказать точнее: в Swift все является объектом какого-то типа). В этом есть большое отличие Swift от Objective-C. Второе - безопасность типов (type safe). Тип переменной, однажды объявленный (если тип явно не указан, то транслятор сам определит его из контекста (называется это type inference)), не может быть изменен. Уже в момент объявления переменной транслятор должен зать тип этой переменнной. И дальше он будет контролировать: в переменную указанного типа невозможно записать значение переменной другого типа. При попытке сделть это транслятор предупредит. Кстати, для совместимости, существует тип AnyObject, который может принимать переменную любого типа. 
Все типы в Swift едины в том смысле что абсолютно для всех переменных мы можем проверить, содержит ли она что-то полезное, была ли она проинициализирована, присвоено ли ей значение, а не только для объектов как в Objective-C.
Понятно, что если мы проинициализировали переменную в момент ее объявления или в инициализаторе, тогда нет смысла проверять. 
В каких же случаях надо проверять? В случаях, когда переменная была объявлена, но ей при этом не было присвоено значение. 
В процессе выполнения программы ей возможно будет оно присвоено, но транслятор об этом не знает, где и когда. Он будет строго реагировать на тот факт, что переменная не проинициализирована. Чтобы "обмануть" транслятор, существует Optionals. Optional это такая обертка над переменной. Мы всегда сможем развернуть ее и посмотреть что там внутри. Ради этого есть конструкция. Транслятор о ней знает. Иногда мы точно знаем, что там под оберткой 100% что-то есть. Можно не проверять, не разворачивать. Это тоже предусмотрено. Об этом потом. И надо понимать, что то, что лежит под оберткой в случае, если там ничего нет, то это оно ведет себя так же как nil в Objective-C. Это надо на случай когда мы пытаемся что-то выполнить для этого "нечто".
Короче говоря, не закрешится, перейдет просто к следующему оператору. 

Как это работает?

Например, 
   var optionalValue: Int?
 Обратите внимание, переменная не проинициализирована. Ей не присвоено значение. Транслятор не ругается только потому, что он видит 
это волшебный значек "?". Эта конструкция Int? называется "optional int". Это значит, что переменная optionalValue может хранить что-то одно из двух (и только): это значение типа Int (структура) или nil - которое говорит об отстутсвии (временном) какого-либо значения внутри. Второе значение (nil) появляется только потому, что это Optionals. Понятие nil больше нигде не появляется и его нельзя использовать для не Optionals переменных. Итак, optionalValue сейчас содержит nil. Как же мы сможем проверить, есть ли что-то под оберткой или нет?
Это можно сделать просто указав эту переменную в условии:
if optionalValue {   ...
} else {
   ...
}
Это называется "Force Unwrapping". Независимо от типа переменной условие вернет true если под оберткой что-то есть. Сейчас важно понять, что если мы попытаемся использовать нашу переменную внутри "истинного" блока, транслятор не даст нам это сделать. Так как он знает точно, 
что эта переменная не была проинициализирована и тут возможен креш. Чтобы использовать эту переменную, надо еще раз обмануть транслятор. Для этого так называемый "Optional Binding": 
   if let unwrappedOptionalValue = optionalValue {       println("\(unwrappedOptionalValue)")
   }
На этот раз мы можем смело использовать значение unwrappedOptionalValue в вычислениях внутри блока. Транслятор уже понимает. Молчит.
Эта конструкция (оператор if let, именно "if let" - это можно понимать как самостоятельный оператор) широко используется. Но понятно не всегда удобно так делать. Наш весь код будет состоять на 30% из таких условий.
Читать такой код будет не очень удобно. Если сразу после имени переменной поставить другой волшебный знак "!", то 
переменную можно использовать везде и без проверки. Транслятор будт спокойно все пропускать. Это ("!") называется "implicitly unwrapped optionals". Единственно, если окажется что в этой переменной нет значения в данный момент, то произойдет креш (ошибка времени выполнения). Итак, первое условие можно переписать используя implicitly unwrapped optionals:
if optionalValue {   println("\(optionalValue!)")
} else {
   ...
}
и все. Транслятор молчит.
После использования переменной ей можно присвоить значение nil: 
optionalValue = nil 
Теперь optionalValue опять не содержит полезных значений. Но! Присвоить nil можно только переменной, объявленной как Optional. Во всех других случаях, если вы объявили переменную, проинициализировали ее (неважно, это let или var), вы не сможете присвоить ей nil. Кстати, всеми вопросами выделения и освобождения памяти занимается Swift. Тут не обязательно присвоить nil, чтобы подсказать среде, что все, объект дальше не нужен, и если на него нет 
больше ссылок, то его можно удалить. Swift сам все посчитает и удалит.
Это почти все, что надо знать про Optionals для того, чтобы начать пробовать.
Дальше начинаются проблемы. Это грубо говоря функции (обычные, встроенные, конструкторы объектов и т.д.), которые могут возвращать что-то. Это что-то может быть Optionals. Вы ставите "!" чтоб не заморачиваться с обертками. А функция реально вернула nil. Тут "креш" неизбежен. Это надо понимать. 
Другой случай. Это преобразование типа (Downcast). Как это принято в полиморфизме, вы получаете переменную базового типа в качестве параметра функции. 
Вам надо преобразовать ее в конкретный тип, который возможно есть где-то в иерархии ниже, чтобы отработать ее конкретное поведение. 
Вы пытаетесь преобразовать. Тут тоже преобразование упирается в Optionals. Если преобразование возможно, то получаете переменную нужного типа, если нет, и
переменная объявлена как Optionals, можно развернуть и проверить. Если нет - "креш". Нельзя присвоить переменной nil.
Конечно если вы точно уверены, что нужный класс наследует базовый (выше в иерархии), то тут все в порядке. Ставьте "!" и все работает!
А если нет (не наследуется), то закрешится. Тут надо разворачивать и проверять. В этом безопасность Swift.
Например:
if let navController = self.menuController()?.mainViewController as? UINavigationController {
    if navController.topViewController.isKindOfClass(SKAboutViewController) {
        self.menuController()?.removeGestures()
    }
}
В первой строке такая вот конструкция: self.menuController()?.mainViewController называется Optional Chaining. Имеется ввиду "?.".
Здесь свойство self.menuController()? является Optionals, поэтому возвращает или объект или nil. Если nil, продолжаем выполнять программу после закрывающей скобки if. Если объект - обращаемся к свойству mainViewController, который должен что-то вернуть. Мы это что-то пытаемся преобразовать к типу UINavigationController. Точнее может сказать интерпретировать как тип UINavigationController. То, что получилось станет значением константы navController. Если удачно получилось преобразование, используем константу в дальнейших вычислениях. Если нет-продолжаем выполнять после закрывающей скобки if. Если бы мы поставили as! вместо as?, и при этом преобразование не удалось, то был бы "креш" (другими словами, as! буквально означает то, что написано: внимание! Возможна проблема). Преимущество as! как вы уже знаете,
в том, что не обязательно оборачивать. Можно было бы написать (уже без условий):
let navController = self.menuController()?.mainViewController as! UINavigationController 
 В Swift 2 Apple предпринял шаги по сокращению использования Optionals. Как сказано Swift blog:
"The SDKs have been updated to annotate API that cannot return nil so you don’t need to use optionals as often."
SDK не будет возвращать nil. Т.е. не будут возвращаться Optionals. 

Литература.

Руководство по Swift от Apple на сайте для разработчиков Apple. Оно же находится в бесплатном доступе на iBook store. Можно открыть через приложение iBook.   
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/index.html.
https://itunes.apple.com/us/book/swift-programming-language/id881256329?mt=11&ign-mpt=uo%3D4

воскресенье, 7 июня 2015 г.

GenStringResources. Application for localization the Xcode projects

Introduction

GenStringResources is a Mac OS application. It requirements MacOS at least 10.6.4 and above, Xcode 4.3 and above. The application uses ibtool and genstrings utilities from Xcode. 
GenStringResources may be used for localization of the Xcode projects in Objective-C.
Application is divided on following parts:
⁃    scanner of the string resources from the Localizable.strings files;
⁃    scanner of the string resources from the XIB files;
⁃    of the string resources creator;
⁃    presenting total information about all string resources for all languages for all projects;
⁃    setting up all options of the application.
Scanner of the resources is passed all Localizable.strings by genstrings utility. It passed by recursive  all folder with modules with the source code of a project. It generates Localizable.strings file with total string resources for the project.
It orders in ascending of key (it is a left part of the line before '=' in the file with resources). Then, it takes the current files with string resources for every language scheme (lproj-folder with according Localizable.strings file) and uses for comparing them with new 
string resources on existing by key. In result, we have total string resources with new string without translating and old string with them. The string without translating are kept in separate Localizable.strings which can be used for translate.
After translate, all new strings can be merged with current resources by the application. 
The same as the scanner of the string resources, the scanner of the XIB, used ibtool utility, builds the similar total file as the previous scanner, just for XIB strings resources.
All operation are carried out in automatic mode for every active project. You can set up active mode for every project in settings. 
So, all string resources are unit in following total resources:
- current dictionary. It contains all phrases with translate for all projects. 
- actual dictionary. In result of scanning that collected all resources for all projects. They are actual on now. Some phrases are translated (they present the current dictionary) and another part is waiting to translate.
After translate, all new strings can be merged with actual resources and become as current. 

User interface

Main window is presented as many documents interface and consists from tools pane and tab bar.
Every document window presented as table with context menu. Tools pane is repeat of the main menu.
Menu item 'Open strings' and 'Start scanning' are calculating and presenting of the string resources.
Menu item 'Open XIBs' and 'Start scanning XIBs' are calculating and presenting of the string resources from the XIBs. 
Menu item 'Total' presents total information about all string resources for all projects in one table.
Menu item 'Settings' are used for setting up all optional parameters. There are path to Xcode project, path to work folder and so on. 
Then menu item for showing readme file and menu item for setup of the tools pane.

Data store

All data is kept in work directory. By default it is '~/Documents/LocalizableStrings'. 
It can be changed in settings. The work directory is divided on three. They are: '/strings', '/XIBs', '/XcodeProjects'. 
Every folder consists from project subdirectories by they name.
In result of scanning all string resources accumulate in the working directory. In main window, the user can see information view. By menu item, user can open information for researching.

User guide


Settings




SwiftOrganizer. Application in Swift for iOS.

SwiftOrganizer is a simple organizer application for an iPhone and for an iPad. 
Was implemented for getting some practice of using the Swift.

Were implemented two types of database:
- Local database on Core Data
- Remote database on the Parse.com server

Also were implemented the following features:
- autolayout (on Interfase Builder Level only)
- switching of the database types from Core Data to remote database and vice versa
- used iCloud key-value storage for switching database types (if you change database type on your iPad, then on your iPhone is changing after some seconds too)
- Core Data on iCloud (fallback store)
- push notifications via Parse.com server
- events can be saved to the Calendar (then you can see your events in the Calendar app on your device) by using EventKit.
- localization app
- local notifications
- sharing via UIActivityViewController
- UIDocument. Enter and Edit files in the Documents folder.
- Document Picker - access to files on remote storage like iCloud, DropBox and etc with download to local Documents folder.
- extension
- todaye widget
- all database function are in the DataBaseKit.framework.

Were applied the following design patterns:
- abstract method;
- observer;
- singleton;
- builder;

Some notes for explain how it works:
On first start are created some tasks by default.
You can add a new task by pressing on button '+' on the navigator bar.
You can select line in tableview to start editing current task.
Any task may be deleted by left swipe gesture on the table view line.
For fetching tasks are used two tab bar. Upper tab bar is used for filtering by category. Bottom tab bar is used for filetering by icons.

Category - entity which used for featching.
There are some predefined category: 'ToDo', 'Work', 'Life', 'Events'.
Icons are used for featching too. They are predefined too.

The Project is in progress.
In future:
- add or remove icons and categories
- make login (at present default user and password are used for login to the backend (parse.com server)).
- will be able to add events to the Reminder app
- local database will be on the iCloud.

Requirements

- Xcode 6
- iOS 8


Tab bars use for filtering task. On the table presented data from local or remote databases. Switch type of a database can be done by settings, by press Activity button, by iCloud from other device, by Today Widget as well.

Today Widget. Current data from database presented on the table. Here you can change of the database type and select task. Application gets parameters from widget and makes appropriate actions.


Action may be done by using of the UIActivityViewController. As you can see were added some buttons in to the activity controller menu.


Sharing data in social networks  by using activity controller:


Some custom controllers:



All source code you can find on GitHub

четверг, 25 июля 2013 г.

Debugging apps by using the network


There is a point which can send the log messages from the iOS app to the instrumental Mac OS X app by using the network. You mustn't connect a device to your Mac for debugging of your app. You can see all logs on the tool-app text view in real time. This tool may be useful for debugging iOS applications in cases when you need to disconnect device. For example in occasion for connecting the external keyboard.

Show of the UIView hierarchy


On the side of the Mac OS X - tool application, you can see a current UIView hierarchy diagram. This diagram is presented before starting the test and may be presented by pressing a button. On the UIView hierarchy diagram, every UIView may be moved by hand. At the same time, you can see the tree of UIViews and every class description, which you can use for creating of the UI-tests. You can store of the diagram in a PDF-file. This possibility may be useful for researching of the UIView hierarchy and bug fixing.


UI-testing


In this project was used UISpec. UISpec is an open-source project for UI-testing. You can integrate UI-tests with your app. All tests may be written in Objective-C or in a special custom scripts language. All information about test-tracking is sent to the desktop application on the network. The advantage of this approach is: you can write UI-tests without limitation. Every iOS developer can write UI-tests without learning of a new script language.