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.
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.
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, 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?
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 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).
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.
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
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.
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
We see that groups in Xcode project navigator and folders in Finder may not be of exact match.
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:
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
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.
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.
The notion of NSInteger and NSNumber may seem confusing at first glance, but in reality it is simple.
NSNumber is a subclass of NSValue – container for C or Objective-C data item. The purpose of NSValue class, and, hence, NSNumber class – to allow items of different data types (ints, floats, chars, pointers, structures, as well as object ids) to be added to collections, such as instances of NSArray, for example. As simple is that!
With that purpose in mind, it’s easy to memorize NSNumber features:
1. it stores and retrieve primitives, but it’s NOT primitive;
2. it can be displayed using %@ format specifier;
3. it is incredible useful when we need to stick a number into NSArray of NSDictionary.
NSInteger also has some features:
1. it is very much like traditional int in C, only it save us from dealing with int/long on 32/64 bit processor architecture;
2. it is a primitive.
We can convert them between each other:
NSInteger myInt = [numberValue integerValue]; //NSNumber to NSInteger//NSInteger to NSNumber
NSNumber myNum = [NSNumber numberWithInteger: integerValue];
NSNumber myNum = @(integer);