Use dynamic user variable with XCODEBUILD

Sometimes we need to do something unusual. For example, configure Xcode project so that it could take command line arguments and use them. Sounds simple enough? Let’s see how it works…(the sample project is here)
To be able to use user defined variable, we need to add it to the project. There are some steps to be completed:
1) Define our variable as preprocessor macros, so it is handled when the build operation is performed:
Select target -> Build settings -> Preprocessing -> Preprocessor Macros and add our variable called LABEL_TEXT for debug and release configurations:

Add User Defined Variable
Add User Defined Variable

2) Now we add user-defined setting and give this User-Defined variable the name LABEL_TEXT and a default value – a string “Jupiter” (as the largest planet in Solar system):

Add User Defined Setting
Add User Defined Setting

3) To be able to access this variable from our app, we need a reference to it. We add a keyLABEL_TEXT to Info.plist and set it to value of our user variable: $(LABEL_TEXT)
Now we can access LABEL_TEXT variable by searching for it’s value in Info.plist. If we build and run sample project using Xcode SDK, we’ll see the label with the name of the largest planed in the Solar system.

Now we jump to the main part – passing a user-defined variable from command line tools. In terminal navigate to project folder (the one, which contains .xcodeproj file). Run the following line:

xcodebuild -sdk iphonesimulator8.4 LABEL_TEXT="Mercury" clean build

it tells Xcode command line tool that we need to build for simulator architecture and clean before the build. Also it passes a new argument to our variable LABEL_TEXT. When the build process is completed, we will see the folder named “build” in our project folder, which, in turn, contains the folder Release-iphonesimucator. Navigate to it, make sure your simulator is open, then run:

xcrun simctl install booted YourAppName.app

(in case of sample project, that will be xcrun simctl install booted UserDefinedLabel.app)
This will install the app into your simulator.
Now we can go to the simulator, press app icon and observe the effect of user-defined variable. Instead of showing the name of the largest planed in Solar system, the label now shows the name of the smallest planet!

Simple as that, we build the app we can run in simulator using the command-line arguments!

iOS8 and custom UIViewControllers transitions

Currently there is a but in iOS8 custom transitions. When the custom transition is complete, i.e. [transitionContext completeTransition: YES] is called, UIWindow shows empty with no view hierarchy at all. That is seen as a black screen which is appearing instead of destination view controller’s view.
The workaround is to add all views back:

[[UIApplication sharedApplication].keyWindow addSubview:  [destinationViewController].view];

Clean solution for now, probably will be fixed soon)

UIKit Animation

Recently I had a chance to get “Learn iPad development and advanced iOS programming” from Equonix Learning Solutions and wanted to share what I have learned about UIKit animations.

UIKit offers several animation properties for UIViews, for more extensive animations it is better to use Core Animation.

Properties which can be animated using UIKit:

  • frame – size and position
  • bounds – size
  • center – position
  • transform – rotation relative to center point
  • alpha – transparency
  • backgroundColor
  • contentStretch – how content fills the available space

UIKit animation is block-based, i.e. animations are passed as blocks to its methods:

+animateWithDuration: animations:
+animateWithDuration: animations: completion:
+animateWithDuration: delay: options: animations: completion:

These are class methods on UIView, so they can be called on several views.
The options: parameter can control:

  • the animation timing curve
  • the number of repetitions
  • whether the animation reverses
  • whether views get touch events during animation
  • whether animation should wait for any other animation to start

Completion: blocks can be used to chain animation together.

Warning: performSelector may cause a leak because its selector is unknown

Complains about:
[someObject performSelector:NSSelectorFromString(@”someMethod”)];

Reason: with ARC the runtime needs to know what to do with the result of the method we are calling. The result can be anything: void, int, char, NSString, id etc. Usually this information is contained in header of the object type we are working with.
What ARC can do with the return value?

  • ignore non-object types (void, int etc)
  • retain object value, then release when it is not used anymore
  • do nothing, assume that return object value will be valid in local scope

The call to methodForSelector: assumes that the return value of the method is an object, but does not retain/release it. So, if the object is supposed to be released, there can be a memory leak.

What if return value is void?
From the compiler perspective it is still an object, so it gives us warning to prevent garbage pointer value being retained/released and crash of an app.

How to fix?

  • static selectors

[_controller performSelector:@selector(someMethod)];
here compiler is able to record all information about the object during compilation and doesn’t need to make assumptions

  • delay execution

[self performSelector:aSelector withObject:nil afterDelay:0.0];
used when acceptable (return object is void and there is no problem to let the runloop cycle once), removes warning by reassuring the compiler that no object can be returned and mismanaged

  • suppress warning

#pragma clang diagnostic ignored “-Warc-performSelector-leaks”
for one line, in case of the whole project macros can be used
Suppressing warnings is ambiguous and not welcomed by many programmers

Concurrency and NSOperation

Multithreading implementations vary a lot, from low-level APIs (like POSIX pthread) to very high-level, which are built on top of low=level and they are friendlier and easier to use. In this respect, NSOperation is higher than GCD, which still has a lot of complexity.

What is what?

  • Thread – a unit of execution, generally expected to share memory and other resources with other threads and managed independently by operating system scheduler. Every UI code runs on main thread.
  • Process – instance of program that is being executed. One process can have one or many threads.
  • Concurrent operation – takes place in a different thread than the one it was started in.
  • Condition – will prevent thread from processing if not met. Used for synchronisation purposes.
  • Critical section – piece of code that access shared resource that must not be accessed by more than one thread.
  • Mutex – “lock”, requirement to ensure that no two concurrent threads are in their critical section at the same time. Mutexes and conditions are examples of Semaphore – protected variable that restricts access to a shared resource.

NSOperation

Operation objects are instances of NSOperation and they encapsulate code that we want to perform. To use NSOperation, we must subclass it. There are two subclasses available, and being used most of the time. For special cases, we can create our own subclasses.
NSInvocationOperation – instantiated by using already existing object and selector from an application.
NSBlockOperation – can use this class to execute various block objects at once.

Features of operation objects:

  • Dependencies – can make an operation execute after another one had finished.
  • Optional completion blocks
  • Prioritizing tasks
  • Any operation can be cancelled at any time
  • Operations commonly are executed by adding them to queue.

Representational State Transfer

REST (Representational State Transfer) is an architecture style for designing network applications. It was introduced and defined in 2000 by Roy Fielding in his doctoral dissertation. Unlike complex mechanisms (For example, Remote Procedure Calls (RPC) where the calling arguments are passed to the remote procedure and the caller waits for a response to be returned from the remote procedure), it uses HTTP to connect between machines.
HTTP is the underlying protocol of World Wide Web. It defines how messages are formatted and transmitted, and what actions web servers and browsers should take in response to various commands.

  • HTTP is stateless, i.e each command executed independently, without any knowledge of the commands that came before it.
  • HTTP is client-server protocol, which treats this two part separately. Client sends request to Web server, which is responsible for document storage and retrieval, it sends the information back.
  • HTTP is cachable, i.e. it allows the client side to cache information and has specifications for when a response can be cached. In this protocol caching is desirable so it’s explicitly designed for it.
RESTful example
RESTful example

RESTful applications use HTTP requests to post data (create and update), read data (make queries) and delete data.
Key components of REST architecture:

  • Resources – identified by URLs
  • A web of resources – a single resource should not be too large and contain too fine-grained details. Instead, the resource should contain links to additional information.
  • Client-server, where one component’s server can be another component’s client
  • No connection state, each request must carry all information required to complete it, and must not rely on previous interactions with client
  • Resources should be cachable when possible, to allow server to specify which resources may be cached and for how long HTTP cache-control headers are used.
  • Proxy servers (intermediary servers) can be used to improve performance.

contentInset and contentOffset properties of UIScrollView

Created and inserted into controller like any other view, UIScrollView needs two additional steps to complete its configuration:

  • set the contents size property, which specifies the size of the scrollable area
  • add view or views that are displayed by scroll view

Even if we haven’t added any views to our UIScrollView yet, running NSLog(@”%@”, scrollView.subviews) will show us two UIImageViews – these are vertical and horizontal scrolling bars.

UIImageViews in UIScrollView
UIImageViews in UIScrollView

Adding one or many subviews depends on our application design, but the scroll view needs to support zooming, the most common solution is to add a single subview that encompasses the entire contentSize and then add additional subviews to that view.
The contentInset property specify a buffer area around the content of the scroll view. We use it, when we need to add padding around the edges of scroll view content.

contentInset
contentInset

It makes content area larger without changing the size of the subview or subview’s content.
To avoid confusion, let’s mention contentOffset property, which is a CGPoint value that defines the top-left corner of the scroll view bounds. It defines the point in the content that is visible at the top left of the scroll view bounds. It is used often, when we need to scroll programmatically as response to user actions (scroll to top in applications with vertical representation of the data).

Core Data is not a relational database

Core Data, according to Core Data Programming Guide, is not a relational database. At the same time, both Core Data and relational database provide searchable and persistent data storage. So, what is the difference?
Relational databases:

  • maintain relations between rows, columns or tables is done by user, options beyond “read” and “write” are very few

Core Data – object graph manager:

  • user can connect object A and B and this connection is kept sync
  • changes in connection trigger notifications and updates
  • handle deletion of objects (cascade or nullify)
  • possible to use without any form of searching – once objects allocated and connected, we can hold onto one of them and walk through everything without needing a fetch request
  • work on objects in memory – can get slow on big amount of data
  • no threading support (need several NSManagedContext instead)

Selectors

Selectors are internal representation of a method name in Objective-C. They are used to SELECT a method to execute for an object, it identifies the method.
Selectors let us treat a method as if it was independent entity, and separate the action from the object that needs to perform it. This is the basis of Target-Action design pattern and is an integral part of Objective-C dynamics typing system.
In Target-Action design pattern the object contains the necessary information to send a message to another object when an event occurs. For example, the button needs to notify the view controller that the button was clicked (touch event) and then the view controller can act upon this information. Button here has a target (to whom) and action method (what message should be sent).

Target-Action example
Target-Action example

Dynamic typing means that object can be sent a message that is not specified in its interface. This allows an object to capture a message and send it to a different object that can respond to this message appropriately. This is known as message forwarding or delegation.

- (void) objDisplay: (id) object
{
    [object displayInfo];
}

There are two ways to get the selector for a method name:

  • @selector() – convert a source-code method name to a selector
  • NSSelectorFromString() – convert a string to a selector

Both return a special data type SEL

Selector code example
Selector code example

Selectors can be executed on arbitrary object via performSelector: and related methods. When we are not sure if the target object defines the method, we should use respondsToSelector: check before trying to perform a selector.
Sample project with selectors and delegates is on Github.

Project files in Finder and Xcode

Imagine we have a basket of apples. I track this apples using a piece of paper and a pencil.

As we can see, although I have a separate categories for green and red apples on paper, in reality all apples are stored together in one basket. A contents of a basket is still reflected on my list correctly. My list obeys certain rules:

  •  if I add an apple on paper, it appears in the basket, otherwise the tracking wouldn’t be of use
  •  if I remove an apple from the basket, the line in my list corresponding to it does not represent an existing object anymore

With this picture in mind, let’s have a look at Xcode project files and how they correspond to files on disk in the project folder

Project in Xcode
Project in Xcode

We see that groups in Xcode project navigator and folders in Finder may not be of exact match.

Project in Finder
Project in Finder

The file named BaseConverter.xcodeproj contains all information about how to build the project. We can open the project by double-click it.
There are some rules present:

  1. The Base converter group looks real, it exists as a folder on disk. If we add more files to this folder through Xcode, they most likely will appear at this folder in Finder as well
  2. The Supporting files group doesn’t show itself on disk, it is just a way to combine some items together inside Xcode project so that’ll be easier to work with them. Contents of this group is real, however, and we can find this files on disk.
  3. Similar story happens with Base Converter group. The group exists only inside Xcode project, but the files are present in Finder.

The groups are used to make a navigation in project more intuitive, but they do not alter file structure on the disk. We create groups, by choosing File -> New -> Group

Frameworks and Products groups are different cases – they don’t correspond to anything in the project folder, but they correspond to real things that the project needs to build and run.

Also, as new users, we may get in trouble by messing with project folder in Finder. The easiest way to avoid this is to perform all our interactions with the project through project window in Xcode.