iOS Basic Development Day 2 - Objective-C 2.0 & iOS Framework
Lecture 06. iOS Programming. Основи Objective-C
-
Upload
maksym-davydov -
Category
Software
-
view
53 -
download
3
Transcript of Lecture 06. iOS Programming. Основи Objective-C
Lecture 06. iOS Programming. Основи Objective-CLviv Polytechnic National University
Davydov M.V.
iOS є UNIX-подібною операційною системою. Ядро платформи – Darwin. Фактично розроблена на основі Mac OS X.
В свою чергу, ядро Darwin базується на BSD та NextStep.
Розмір операційної системи на мобільному пристрої складає близько 2 ГБ.
Основними елементами платформи є: Cocoa Touch Layer, Media Layer,
Core Services та Core OS
Cocoa Touch – найвищий рівень API.
В свою чергу складається з наборів бібліотек: Cocoa Touch Frameworks,
Address Book UI, Event Kit UI, Game Kit,
iAd, MapKit,
Message UI, UI Kit та ін.
Фактично Cocoa Touch Layer – це спрощення настільної версії Cocoa з доданими функціями
розпізнавання жестів, анімації та технології multi-touch.
Media Layer складається з: Asset Library, AVFoundation,
Core Audio, Core Graphics,
Core MIDI, Core Text,
Core Video, Image IO,
Media Player, Open AL,
OpenGL ES, Quartz Core та інших.
Core Services Layer складається з:
Address Book,
CFNetwork, Core Data,
Core Foundation, Core Location, Core Media,
Core Telephony, Event Kit,
Foundation, Store Kit та інших.
Функції рівня Core OS базуються на стандарті POSIX.
POSIX-standard (Portable Operating System Interface for Unix) – це набір стандартів, які описують інтерфейси між операційною системою та прикладною програмою, бібліотеку мови C.
Стандарт створений для забезпечення сумісності різних UNIX-подібних операційних систем та
портованості прикладних програм на рівні вихідного коду прикладних програм.
Основним засобом розробки на мобільній платформі iOS є XCode. Інтерфейс середовища розробки XCode є доволі незвичним, проте містить всі необхідні засоби для розробки включаючи засоби перевірки синтаксису,
розробки інтерфейсу, компілятори та відлагоджувачі.
Основними файлами проекту в XCode є: .h - “header” (or interface file) – файл заголовків
.m - “message” (or implementation file) – файл з реалізацією (Objective C)
.mm - “message” (or implementation file) – файл з реалізацією (Objective C++)
.swift - вихідні файли на мові програмування Swift .xib – (XML interface builder file) – файл ресурсів
До набору інструментів XCode входить емулятор мобільних пристроїв iPhone та
iPad.
Програмування для платформи iOS передбачає наслідування двох ключових парадигм – об’єктно-
орієнтованого програмування та шаблону проектування MVC.
MVC на iOS здійснюється на основі: View - вид забезпечується класами UIView та
UIViewController Controller - поведінка контролера здійснюється через три ключові технології – делегування, повідомлення
та target-action.
Класи UIView та UIVIewController відповідають за розміщення елементів управління.
Види є ієрархічними та будуються як дерево з під-видами.
Вид може бути або головним або в складі іншого виду, доданим за допомогою методу addSubview.
UIViewController не є компонентом Controller в MVC. Він реалізує лише додаткову функціональність для
навігації.
Згідно з концепцією Target-action, програма розділена на об’єкти, які динамічно встановлюють зв’язок один з
одним на основі повідомлень.
The term target–action design paradigm refers to a kind of software architecture, where a computer program is
divided into objects which dynamically establish relationships by telling each other which object they
should target and what action or message to send to that target when an event occurs.
This is especially useful when implementing graphical user interfaces, which are by nature event-driven.
[button setTarget: self]; [button setAction: @selector(doSomething)];
[button setTarget: self]; [button setAction: NSSelectorFromString([textField stringValue])];
Важливо - ":" є частиною назви методу
Це різні селектори @selector(doSomething) @selector(doSomething:)
Перший вказує на метод без параметрів другий - з параметрами
This is possible because, under Objective-C, methods are represented by a selector, a simple
string describing the method to be called.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(useNotificationWindowDidLoad:) name:@"WindowDidLoad" object:nil];
-(void)useNotificationWindowDidLoad:(NSNotification *) notification { …
}
When a message is sent, the selector is sent into the ObjC runtime, matched against a list of available methods, and the method's implementation is called. The implementation of the method is looked up at runtime, not compile time.
Objective-C Language⦿ Objective-C is an object oriented language. ⦿ follows ANSI C style coding with methods
from Smalltalk
⦿ Flexible almost everything is done at runtime. ● Dynamic Binding ● Dynamic Typing ● Dynamic Linking
Apple and Mac OS X⦿ NeXT is taken over by Apple in 1996 and
put Steve Jobs and his Objective-C libraries to work
⦿ Redesigned Mac OS to use objective-C similar to that of NeXTSTEP
⦿ Developed a collection of libraries named “Cocoa” to aid GUI development
⦿ Release Mac OS X (ten), which was radically different than OS 9, in March 2001
The Cocoa API⦿ Developed by Apple from NeXTSTEP and
OPENSTEP
⦿ Has a set of predefined classes and types such as NSnumber, NSstring, Nsdate, etc.
⦿ NS stands for NeXT-STEP ⦿ Includes a root class NSObject where words like
alloc, retain, and release come from
Dynamic Language⦿ Almost everything is done at runtime
⦿ Uses dynamic typing, linking, and binding
⦿ This allows for greater flexibility
⦿ Minimizes RAM and CPU usage
To Import or Include?⦿ C/C++’s #include will insert head.h into
the code even if its been added before.
⦿ Obj-C’s #import checks if head.h has been imported beforehand.
#import “head.h”
Inherited from C⦿ all basic types ⦿ functions (non-members) ⦿ pointers ⦿ operators ⦿ all main instructions (cycles, conditions) ⦿ global and static variables
New in Objective C⦿ for … in … loop ⦿ Introduced in Objective-C 2.0 (“fast
enumeration”)
for(Item_Type *item in Collection_of_Items) {
//do whatever with the item Nslog(@” Looking now at %@”, item); }
Note: %@ in the NSLogconverts whatever is passed (in this case item) to a string
Main Funciton – подібно до мови C
#import <someheaders.h>
int main(int argc, const char *argv[]) { @autoreleasepool { //your code here******* // об’єкти, додані в autorelease пул з використанням // виклику autorelease або методів, які вертають тимчасові
// об’єкти будуть автоматично знищені
return 0; }
}
Вивід тексту - printf, NSLog⦿ Two standard functions you see used
⦿ printf() – same as C ○ printf(“Hi Lynne”); //this is actual C code
⦿ NSLog() ○ NSLog(@”Hi Lynne”); //this is strictly Objective-
C
Класи (об’єкти) — не класи C++!!!
⦿ Have both definition file and implementation file : classname.h and classname.m
⦿ Similar to how have .h and .cpp in C++
Означення класу (інтерфейс)#import <Cocoa/Cocoa.h>…@interface <Назва класу> : <Батьківський клас>{
// відкриті поля }// методи і атрибути@end
Приклад інтерфейсу (класу)#import <Cocoa/Cocoa.h>@interface Node : NSObject {
Node *link;int contents;
}+(id)new; //static(class) member-(void)setContent:(int)number;-(void)setLink:(Node*)next;-(int)getContent;-(Node*)getLink;@end
Node.h
Реалізація інтерфейсу
#import "interface_file.h"
@implementation <назва класу>// приватні поля класу// реалізація відкритих і // приватних методів@end
Приклад реалізації (класу)#import “Node.h”@implementation Node+(id)new { return [Node alloc];}-(void)setContent:(int)number {contents = number;}-(void)setLink:(Node*)next{
[link autorelease];link = [next retain];
}-(int)getContent { return contents; }-(Node*)getLink { return link; }@end
Node.m
Приклад інтерфейсу (класу)@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (retain) WindowController *myWindowController; @property (weak) IBOutlet DesktopUIMenu *desktopMenu; @property (nonatomic, retain) NSURL* inputImageURL;
@end
AppDelegate.h
Приклад реалізації (класу)@interface AppDelegate () {
// приватні поля NSOutputStream *_outputStream; NSInputStream *_inputStream; } @end
@implementation AppDelegate { // приватні поля NSURL* _inputImageURL; }
@synthesize NSURL* inputImageURL = _inputImageURL; // методи - (void)applicationWillTerminate:(NSNotification *)aNotification{ // Insert code here to tear down your application [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isOpenGLIsLoaded"]; }
@end
AppDelegate.m
Оголошення методів
C++ syntax
Objective-C syntax
void function(int x, int y, char z);
Object.function(x, y, z);
-(void) method:(int)x, (int)y, (char)z;
[Object function:x, y, z];
- (void)driveCar:(Car *)car withPerson:(Person *)person;[carController driveCar:car withPerson:person];
+ і – в оголошенні методу⦿ Оголошення методу в інтерфейсі починається з «+» або «-»
⦿ + означає, що це — “метод класу (типу)” який викликання через посилання на тип (як статичні методи в Java)
⦿ - означає, що це — “метод об’єкту”, який викликається через посилання на об’єкт (як звичайні методи у Java)
Створення екземплярів об’єктівClassName *object = [[ClassName alloc] init]; ClassName *object = [[ClassName alloc] initWith* ];
● NSString* myString = [[NSString alloc] init]; ● Nested method call. The first is the alloc method called on NSString itself. This is
a relatively low-level call which reserves memory and instantiates an object. The second is a call to init on the new object. The init implementation usually does basic setup, such as creating instance variables. The details of that are unknown to you as a client of the class. In some cases, you may use a different version of init which takes input:
ClassName *object = [ClassName method_to_create];● NSString* myString = [NSString string]; ● Some classes may define a special method that will in essence call alloc followed by some kind of
init
Creating an Object
Виклик методу — це надсилання повідомлення⦿ Almost every object manipulation is done by
sending objects a message ⦿ Two words within a set of brackets, the object
identifier and the message to send.
Like C++ or Java’s Identifier.message()
[Identifier message ]
Доступ до полів класу — лише через методи або властивості
[object setXXXMethod:value1];
[object setXXXMethod:value1 with:secondArgument];
C++ VS. Objective-C⦿ Adds OOP,
metaprogramming and generic programming to C
⦿ Comes with a std library
⦿ Has numerous uses ⦿ Large and complex
code for OOP
⦿ Only adds OOP to C ⦿ Has no standard
library; is dependant on other libraries
⦿ Mostly used for application building
⦿ Simpler way of handling classes and objects
Keyword: id⦿ The word ‘id’ indicates an identifier for an
object much like a pointer in c++ ⦿ This uses dynamic typing ⦿ For example, if Pen is a class…
extern id Pen;
id myPen;
myPen = [Pen new ];
id work like pointers to objects.
Memory Allocation⦿ Objects are created dynamically through
the keyword, “alloc” ⦿ Objects are automatically deallocated in
latest Objective-C through automatic reference counting
NSInteger and NSUintegerNSInteger number; (Like long in C) NSUIntneger another; (Like unsigned long in C)
● Objective-C data types that are 32-Bits on 32-Bit platforms and 64-bits on 64-bit platforms
NSStringNSString *theMessage = @”hello world”;
● Number of characters in a string ○ NSUInteger charCount = [theMessage length];
● Test if 2 strings equal ○ if([string_var_1 isEqual: string_var_2])
{ //code for equal case }
String literal in Objective-C⦿ Begins with the @ symbol ⦿ @”Lynne Grewe”;
Some Examples NSString *myString = @”Hello World”;
int len = [myString length];
OR int len = [@”Hello World” length];
OR NSString *myString = [[NSString alloc] initWithString:@”Hello World”]; int len = [myString length];
Formatting Strings in output NSLog
int a = 1; float b = 33.22; char c = ‘A’; NSLog(@”Integer %d Float: %f Char: %c”, a, b, c);
NSString ---not changeable⦿ International (any language) strings using Unicode. ⦿ Compiler will create an NSString for you using
@“foo” notation. ⦿ An NSString instance can not be modified! They
are immutable. ⦿ Usual usage pattern is to send a message to an
NSString and it will return you a new one. ● self.display.text = [self.display.text stringByAppendingString:digit]; ● self.display.text = [NSString stringWithFormat:@“%g”, brain.operand]; // class
method
⦿ Tons of utility functions available (case conversion, URLs, substrings, type conversions, etc.).
NSMutableString ---changeable⦿ Mutable version of NSString. Somewhat rarely
used.
⦿ Can do some of the things NSString can do without creating a new one (i.e. in-place changes).
NSMutableString *ms = [[NSMutableString alloc] initWithString:@“0.”]; NSMutableString *ms = [NSMutableString stringWithString:@“0.”]; // inherited from
NSString [ms appendString:digit];
NSNumber⦿ Object wrapper around primitive types
like int, float, double, BOOL, etc. NSNumber *num = [NSNumber numberWithInt:36]; float f = [num floatValue]; // would return 36 as a float (i.e. will convert types)
⦿ Useful when you want to put multiple numeric primitive types in a collection (e.g. NSArray or NSDictionary).
NSValue⦿ Generic object wrapper for other non-
object data types. CGPoint point = CGPointMake(25.0, 15.0); // CGPoint is a C
struct NSValue *pointObject = [NSValue valueWithCGPoint:point];
NSData⦿ “Bag of bits.” Used to save/restore/
transmit data throughout the iOS SDK.
NSDate⦿ “Used to find out the time right now or to
store past or future times/dates. ⦿ See also NSCalendar, NSDateFormatter,
NSDateComponents.
NSArray – holds fixed array of points to objectsNSArray *thearray = [NSArray arrayWithObjects:o1,o2,o3,o4,
nil];
//get element [thearray objectAtIndex:0]; //element at index 0
Example
NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTImeInterval:24.0*60.0*60.0]; //add a day NSDate *yesterday = [now dateByAddingTimeInterval:-24.0*60.0*60.0]; //minus a
day
//array of Dates NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday];
//get elements in array NSDate *first = [dateList objectAtIndex:0];
Methods are: count = gets number of items in arrayobjectAtIndex:i = returns element i of array (starting from 0)
Note: you can not add or remove a pointer from an NSArray---fixed once created
NSArray – cycle through with for loop
NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTImeInterval:24.0*60.0*60.0]; //add a day NSDate *yesterday = [now dateByAddingTimeInterval:-24.0*60.0*60.0]; //minus a day
//array of Dates NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday];
//get elements in array NSDate *first = [dateList objectAtIndex:0];
NSUInteger dateCount = [dateList count]; for(int i=0; i<dateCount; i++) { NSDAte *d = [dateList objectAtIndex:i]; NSLog(@” Date is %@”, d); }
Methods are: count = gets number of items in arrayobjectAtIndex:i = returns element i of array (starting from 0)
NSArray – cycle through with for loop OPTION 2
NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTImeInterval:24.0*60.0*60.0]; //add a day NSDate *yesterday = [now dateByAddingTimeInterval:-24.0*60.0*60.0]; //minus a day
//array of Dates NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday];
//get elements in array NSDate *first = [dateList objectAtIndex:0];
For(NSDate *d in dateList) { NSLog(@” Date is %@”, d); }
This is a “for in” loop --- convinient
NSMutableArray – changeable array of pointers to objects.NSMutableArray *thearray = [NSArray arrayWithObjects:o1,o2,o3,o4,
nil];
//get element [thearray objectAtIndex:0]; //element at index 0
Example NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTImeInterval:24.0*60.0*60.0]; //add a day NSDate *yesterday = [now dateByAddingTimeInterval:-24.0*60.0*60.0]; //minus a day
//array of Dates NSMutableArray *dateList = [NSMutableArray array];
//set elements [dateList addObject:now]; [dateList addObject:tomorrow]; [dateList addObject:yesterday];
Methods are: array = gets empty NSMutableArrayaddObject:obj = adds as next element the obj to array
Note: you can add or remove a pointer from an NSMutableArray
NSDictionary⦿ Immutable hash table. Look up objects using
a key to get a value. + (id)dictionaryWithObjects:(NSArray *)values forKeys:(NSArray *)keys; + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
⦿ Creation example: NSDictionary *base = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:2], @“binary”, [NSNumber numberWithInt:16], @“hexadecimal”, nil];
⦿ Methods ● - (int)count; ● - (id)objectForKey:(id)key; ● - (NSArray *)allKeys; ● - (NSArray *)allValues;
see documentation (apple.com) for more details
NSMutableDictionary⦿ Changeable + (id)dictionaryWithObjects:(NSArray *)values forKeys:(NSArray *)keys; + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
⦿ Creation : + (id)dictionary; //creates empty dictionary
⦿ Methods - (void)setObject:(id)anObject forKey:(id)key; - (void)removeObjectForKey:(id)key; - (void)removeAllObjects; - (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
see documentation (apple.com) for more details
Other useful Objective-C data classes⦿ NSSet, NSMutableSet, NSOrderedSet,
NSMutableOrderedSet
Objective-C
Memory management Memory management is semi-automatic:
The programmer must allocate memory for objects either a) explicitly (alloc) or b) indirectly using a convenience constructor
No need to de-allocate
Objective-C memory management1) Old mode - MRC (Manual Reference Counting) 2) New mode - ARC (Automatic Reference Counting) These modes could not be mixed!!!
Automatic Reference Counting⦿ Objective C uses ‘AUTOMATIC reference
counting' as default memory management
⦿ keeps an internal count of how many times an Object is 'needed'.
⦿ System makes sure that objects that are needed are not deleted, and when an object is not needed it is deleted.
AllocationAllocation happens through the class method alloc.
The message ‘alloc’ is sent to the class of the requested object. Alloc is inherited from NSObject. Every alloc creates a new instance (=object)
[HelloWorld alloc]; The class creates the object with all zeros in it and
returns a pointer to it. HelloWorld *p = [HelloWorld alloc]; The pointer p now points to the new instance. Now we send messages to the instance through p.
The reference counter• Every instance has a reference counter. It
counts how many references are retaining the object. The counter is 1 after allocation. It does not count how many references exist to the object
• Sending the retain message to the object increases the reference counter by 1.
• Sending the release message decreases the reference counter by 1.
• No need to do either if using ARC.
reference counter = retain counter
• When the reference counter reaches zero, the object is automatically de-allocated. The programmer does not de-allocate.
• The programmer only does: alloc retain release
Rules for memory management
• With no ARC: The method that does an alloc or a retain must also do a release, it must maintain the balance between:
(alloc or retain) and (release)
• If a method does alloc and returns a pointer to the created object then the method must do an autorelease instead of release.
Autorelease pool without ARC• With no ARC: For autorelease to work the
programmer must create an autorelease pool, using:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
• When Cocoa is used then the autorelease pool is created automatically – the programmer does not need to do it.
• To release the pool and all objects in it, do: [pool release];
Autorelease pool new syntax (works with and without ARC)
@autoreleasepool{ // Code that creates // autoreleased objects.}
Convenience Constructors• This is a class method that allocates and
initializes an object. The programmer is neither doing alloc nor init.
• Example:
+(id)studentWithName :(NSString*)name AndGpa:(float)gpa { id newInst = [[self alloc]initStudent:name :gpa]; return [newInst autorelease]; }
Convenience Constructors
• Essential: the method sends alloc to self which is the Student class object
• Essential: the method autoreleases the instance, because it returns a pointer to the created instance
• Not essential: This example uses an existing initializer, it could use something else or initialize the Student data directly
Convenience Constructors
Calling the convenience constructor: id stud = [Student studentWithName:@"Johnnie" AndGpa: 3.8];
The message is sent to the Student class object and returns a pointer to it, the pointer is assigned to stud
The calling code does neither alloc nor init An autorelease pool must be in place
Код, який працює з ARC і без ARC
NSString *nsstring = [[NSString alloc] initWithFormat:format_message arguments:valist];
… #if !__has_feature(objc_arc) [nsstring release]; #endif
ARC не працює в структурах і класах С/C++
struct Data { NSMutableArray *array; };
error: ARC forbids Objective-C objs in structs or unions NSMutableArray *array;
Але можна зберігати вказівник без підрахунку посилань
struct Data
{
NSMutableArray __unsafe_unretained *array;
};
As described previously, the compiler doesn’t manage variables with the __unsafe_unretained ownership qualifier. You have to take care of ownership yourself to avoid a memory leak or the application will crash.
Bridging
Object Type Variables Cannot Be Members of struct or union in C Language When you add a member variable of Objective-C object type to C struct or union, a compile error occurs. struct Data
{
NSMutableArray *array;
};
error: ARC forbids Objective-C objs in structs or unions NSMutableArray *array;
__bridge cast
You can use __bridge cast as id obj = [[NSObject alloc] init];
void *p = (__bridge void *)obj;
…
id o = (__bridge id)p;
Dangerous! P does not have ownership!!!
__bridge_retained castПриведення типу зі збільшенням кількості посилань:id obj = [[NSObject alloc] init]; void *p = (__bridge_retained void *)obj;
The above source code can be rewritten for a non-ARC environment as follows. /* non-ARC */ id obj = [[NSObject alloc] init];
void *p = obj; [(id)p retain];
Суміщення Objective-C і Swift
• З Objective-C можна викликати код на C, C++, відправляти повідомлення об’єктам Swift
• Зі Swift можна відправляти відправляти повідомлення об’єктам Objective-C
Bridging header - має імпотувати всі Objective-C класи, які будуть використовуватися зі Swift
Test-Bridging-Header.h#ifndef Test_Bridging_Header_h #define Test_Bridging_Header_h
#import "Test.h"
#endif /* Test_Bridging_Header_h */
Calling Objective-C from Swift
#import "Test.h"
@implementation Test
- (void) someMethod: (int) a { NSLog(@"SomeMethod with a=%d", a); }
@end
Test.m
Test.h#import <Foundation/Foundation.h>
@interface Test : NSObject
@property (strong, nonatomic) id someProperty;
- (void) someMethod : (int)a;
@end
Використання Objective-C класу зі Swift
let t = Test(); t.someMethod(24);
Виклик Swift коду з Objective-C
class SomeSwiftClass : NSObject { func showLog(x: Test) { print("Hello Swift ", x.getInt()) } }
1. Створити Swift клас
Виклик Swift коду з Objective-C
#import "Test.h" // import swift declarations "<ProjectName>-Swift.h" #import "Test1-Swift.h"
@implementation Test
- (void) someMethod: (int) a { NSLog(@"SomeMethod Ran %d", a); SomeSwiftClass * c = [[SomeSwiftClass alloc] init]; [c showLogWithX:self]; }
-(int)getInt { return 24; }
@end
2. Імпортувати файл заголовків зі Swift
ЗауваженняНазви методів змінюються з використанням правил іменування Objective-C:
Swift:class SomeSwiftClass : NSObject { func showLog(x: Test, a: Int) { print("Hello Swift ", x.getInt(), " ", a) } } Згенерований Objective-C заголовок:
SWIFT_CLASS("_TtC5Test114SomeSwiftClass") @interface SomeSwiftClass : NSObject - (void)showLogWithX:(Test * _Nonnull)x a:(NSInteger)a; - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; @end
Згенеровані назви методів можна взнати, якщо перейти на означення класу SomeSwiftClass з Objective-C
Рекомендована література