SlideShare a Scribd company logo
From C++ to Objective-C
This document is designed to act as a bridge between C++ and Objective-C.
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 1
Why Objective-C?
#import "AppDelegate.h"
#import <ScriptingBridge/ScriptingBridge.h>
#import <objc/runtime.h>
NSString * const TerminalNotifierBundleID = @"fr.julienxx.oss.terminal-notifier";
NSString * const NotificationCenterUIBundleID = @"com.apple.notificationcenterui";
NSString *_fakeBundleIdentifier = nil;
@implementation NSBundle (FakeBundleIdentifier)
- (NSString *)__bundleIdentifier;
{
if (self == [NSBundle mainBundle])
{
return _fakeBundleIdentifier ? _fakeBundleIdentifier : TerminalNotifierBundleID;
}
else
{
return [self __bundleIdentifier];
}
}
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 2
A short history of Objective-C
Timeline of Java, C, C#, C++ and Objective-C
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 3
C++ Objective-C
Syntax overview
//In file Foo.h
#pragma once //compilation guard
class Foo
{
...
};
//In file Foo.cpp
#include "Foo.h"
...
//In file Foo.h
//class declaration, different from
//the "interface" Java keyword
@interface Foo : NSObject
{
...
}
@end
//In file Foo.m
#import "Foo.h"
@implementation Foo
...
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 4
C++ Objective-C
Syntax overview
class Foo
{
double x;
public:
int f(int x);
float g(int x, int y);
};
int Foo::f(int x) {...}
float Foo::g(int x, int y) {...}
@interface Foo : NSObject
{
double x;
}
-(int) f:(int)x;
-(float) g:(int)x :(int)y;
@end
@implementation Foo
-(int) f:(int)x {...}
-(float) g:(int)x :(int)y {...}
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 5
C++ Objective-C
Syntax overview
class Foo
{
public:
int x;
int apple();
protected:
int y;
int pear();
private:
int z;
int banana();
};
@interface Foo : NSObject
{
@public
int x;
@protected
int y;
@private
int z;
}
-(int) apple;
-(int) pear;
-(int) banana;
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 6
Root class, type id, nil and Nil values
Unlike C++, Objective-C defines a root class. Every
new class should be a descendant of the root class. In
Cocoa, that class is NSObject, and it provides a huge
number of facilities for the run-time system.
OBJC_ROOT_CLASS
@interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
+ (void)load;
+ (void)initialize;
- (instancetype)init
+ (instancetype)new OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
- (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer");
- (void)finalize OBJC_DEPRECATED("Objective-C garbage collection is no longer supported");
- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("")
+ (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
+ (NSUInteger)hash;
+ (Class)superclass;
+ (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");
+ (NSString *)description;
+ (NSString *)debugDescription;
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 7
Root class, type id, nil and Nil values
“id” is a data type of object identifiers in Objective-C,
which can be use for an object of any type no matter
what class does it have. “id” is the final supertype of all
objects.
By default, it is legal to send a message (call a
method) to nil. The message is just ignored. The code
can be greatly simplified by reducing the number of
tests usually made with the null pointer.
NSString *name = @"dobegin";
id data = name;
NSURL *site = data;
NSString *host = site.host; // oops! runtime error!
// "unrecognized selector sent to instance"
#if !defined(nil)
#define nil (id)0
#endif
// For example, this expression...
if (name != nil && [name isEqualToString:@"Steve"]) { ... }
// ...can be simplified to:
if ([name isEqualToString:@"Steve"]) { ... }
#if !defined(Nil)
#define Nil (Class)0
#endif
#inlcude <objc/runtime.h>
Class foo = objc_allocateClassPair([NSString class], "NSDictionary", 0);
if (foo != Nil)
{
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 8
Messages and transmission
A message is the name of a method, and any parameters
associated with it, that are sent to, and executed by, an
object. To get an object to do something, you send it a
message telling it to apply a method.
● Search the class’s method cache for the IMP
● If not found, search the class hierarchy for the IMP
● Jump to IMP if found (jmp assembly instruction)
● If not found, jump to _objc_msgforward
● All objects can forward messages they don’t respond
id objc_msgSend(id receiver, SEL method, ...);
[receiver аddObject: otherObject];
objc_msgSend(receiver, 12, otherObject);
addObject(receiver, otherObject);
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 9
Messages and transmission
In C++, code cannot be compiled if a method is called
on an object that does not implement it. In Objective-C,
there’s a difference: one can always send a message to
an object. If it can’t be handled at run-time, it will be
ignored (and raise an exception); moreover, instead of
ignoring it, it can forward the message to another
object.
-(void) forwardInvocation:(NSInvocation*)anInvocation
{
//if we are here, that is because the object cannot handle
//the message of the invocation
//the bad selector can be obtained by sending "selector"
//to the object "anInvocation"
if ([anotherObject respondsToSelector:[anInvocation selector]])
[anInvocation invokeWithTarget:anotherObject];
else //do not forget to try with the superclass
[super forwardInvocation:anInvocation];
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 10
Messages and transmission
Delegation is common with user interface elements in
Cocoa (tables, outlines. . . ), taking advantage of the
ability to send a message to an unknown object. An
object can, for example, delegate some tasks to an
assistant.
-(void) performHardWork:(id)task
{
if ([assistant respondsToSelector:@selector(performHardWork:)])
[assistant performHardWork:task];
else
[self findAnotherAssistant];
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 11
Protocols
A formal protocol is a set of methods that must be
implemented in any conforming class. This can be seen
as a certification regarding a class, ensuring that it is
able to handle everything that is necessary for a given
service. A class can conform to an unlimited number of
protocols.
@protocol NSObject
- (BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;
@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
- (instancetype)self;
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
- (BOOL)isProxy;
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
- (BOOL)respondsToSelector:(SEL)aSelector;
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
@property (readonly, copy) NSString *description;
@optional
@property (readonly, copy) NSString *debugDescription;
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 12
Class categories
@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding,
NSFastEnumeration>
@property (readonly) NSUInteger count;
- (ObjectType)objectAtIndex:(NSUInteger)index;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithObjects:(const ObjectType _Nonnull [_Nullable])objects
count:(NSUInteger)cnt NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
NS_DESIGNATED_INITIALIZER;
@end
@interface NSArray(NSArrayCreation)
+ (instancetype)array;
+ (instancetype)arrayWithObject:(ObjectType)anObject;
+ (instancetype)arrayWithObjects:(const ObjectType _Nonnull [_Nonnull])objects
count:(NSUInteger)cnt;
+ (instancetype)arrayWithObjects:(ObjectType)firstObj, ...
NS_REQUIRES_NIL_TERMINATION;
+ (instancetype)arrayWithArray:(NSArray<ObjectType> *)array;
- (instancetype)initWithObjects:(ObjectType)firstObj, ...
NS_REQUIRES_NIL_TERMINATION;
- (instancetype)initWithArray:(NSArray<ObjectType> *)array;
- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
/* Reads array stored in NSPropertyList format from the specified url. */
- (nullable NSArray<ObjectType> *)initWithContentsOfURL:(NSURL *)url error:(NSError
**)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/* Reads array stored in NSPropertyList format from the specified url. */
+ (nullable NSArray<ObjectType> *)arrayWithContentsOfURL:(NSURL *)url
error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0),
tvos(11.0)) NS_SWIFT_UNAVAILABLE("Use initializer instead");
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 13
Properties
The notion of property can be met when defining classes. The keyword @property can be associated to a data member, to tell how the accessors can be
automatically generated by the compiler. It aims at writing less code and save some development time.
A property is declared according to the following template :
@property type name;
or
@property(attributes) type name;
If they are not given, the attributes have a default value; otherwise, they can be redefined to answer the questions stated in the previous section. They
can be :
● readwrite (default) or readonly to tell if the property should have both getter/setter or only the getter;
● assign (default), retain or copy, to tell how the value is stored internally;
● nonatomic to prevent thread-safety guards to be generated. They are generated by default (atomic).
● getter=..., setter=... to change the default name of the accessors.
@property (copy, nonatomic, nonnull) NSString *foo;
@property (copy, nonatomic, nonnull) NSString *str;
@property (strong, nonatomic, nullable) NSNumber *bar;
@property (copy, nonatomic, null_resettable) NSString *baz;
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 14
Working with Blocks
Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain
variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when
executed.
As a local variable:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a property:
@property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes);
As a method parameter:
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
As an argument to a method call:
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
As a typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 15
Working with Blocks
By default blocks are created on the stack. Meaning they only exist in the scope they have been created in.
//property
@property (nonatomic, copy) SomeBlockType someBlock;
//local variable
someBlockType someBlock = ^{
NSLog(@"hi");
};
[someArray addObject:[someBlock copy]];
Blocks capture values from the enclosing scope.
__weak SomeObjectClass *weakSelf = self;
SomeBlockType someBlock = ^{
SomeObjectClass *strongSelf = weakSelf;
if (strongSelf) {
[strongSelf someMethod];
}
};
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 16
Working with Blocks
Use __block Variables to Share Storage
If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration. This means that
the variable lives in storage that is shared between the lexical scope of the original variable and any blocks declared within that scope.
__block int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
anInteger = 100;
};
testBlock();
NSLog(@"Value of original variable is now: %i", anInteger);
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 17
Memory management
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 18
Basic Memory Management Rules
Memory management
The memory management model is based on object ownership. Any object may have one or more owners. As long as an object has at least one owner, it
continues to exist. If an object has no owners, the runtime system destroys it automatically. To make sure it is clear when you own an object and when you do
not, Cocoa sets the following policy:
● You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”.
● You can take ownership of an object using retain
A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its
invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want
to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation.
● When you no longer need it, you must relinquish ownership of an object you own
You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an
object is therefore typically referred to as “releasing” an object.
● You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated explicitly.
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 19
NSAutoreleasePool
Memory management
An object that supports Cocoa’s reference-counted memory management system. An autorelease pool stores objects that are sent a release message when the
pool itself is drained. NSAutoreleasePool object contains objects that have received an autorelease message and when drained it sends a release message to
each of those objects. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is drained (it may
be longer if the object is subsequently retained). An object can be put into the same pool several times, in which case it receives a release message for each
time it was put into the pool.
@autoreleasepool {
// Code that creates autoreleased objects.
}
Like any other code block, autorelease pool blocks can be nested:
@autoreleasepool {
// . . .
@autoreleasepool {
// . . .
}
. . .
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 20
NSAutoreleasePool
Memory management
Use local autorelease pool blocks to reduce peak memory footprint:
NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
@autoreleasepool {
NSError *error;
NSString *fileContents = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
}
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 21
Grand Central Dispatch
Multithreading
Grand Central Dispatch (GCD) is a technology developed by Apple Inc. to optimize application support for systems with multi-core processors and other
symmetric multiprocessing systems. It is an implementation of task parallelism based on the thread pool pattern.
● Dispatch Queues are objects that maintain a queue of tasks, either anonymous code blocks or functions, and execute these tasks in their turn. The library
automatically creates several queues with different priority levels that execute several tasks concurrently, selecting the optimal number of tasks to run
based on the operating environment. A client to the library may also create any number of serial queues, which execute tasks in the order they are
submitted, one at a time
- (IBAction)analyzeDocument:(NSButton *)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDictionary *stats = [myDoc analyze];
dispatch_async(dispatch_get_main_queue(), ^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
});
});
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 22
Grand Central Dispatch
● Dispatch Sources are objects that allow the client to register blocks or functions to execute asynchronously upon system events, such as a socket or file
descriptor being ready for reading or writing, or a POSIX signal.
dispatch_source_t CreateDispatchTimer(uint64_t interval,
uint64_t leeway,
dispatch_queue_t queue,
dispatch_block_t block)
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0, 0, queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}
Multithreading
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 23
Grand Central Dispatch
● Dispatch Groups are objects that allow several tasks to be grouped for later joining. Tasks can be added to a queue as a member of a group, and then the
client can use the group object to wait until all of the tasks in that group have completed.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, queue, ^{
// Some asynchronous work
});
// Do some other work while the tasks execute.
// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// Release the group when it is no longer needed.
dispatch_release(group);
Multithreading
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 24
Grand Central Dispatch
● Dispatch Semaphores are objects that allow a client to permit only a certain number of tasks to execute concurrently.
// Create the semaphore, specifying the initial pool size
dispatch_semaphore_t fd_sema = dispatch_semaphore_create(getdtablesize() / 2);
// Wait for a free file descriptor
dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER);
fd = open("/etc/services", O_RDONLY);
// Release the file descriptor when done
close(fd);
dispatch_semaphore_signal(fd_sema);
Multithreading
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 25
Grand Central Dispatch
● Create singleton using GCD's dispatch_once
+ (instancetype)sharedInstance
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Multithreading
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 26
Key-Value Coding
Key-value coding is a mechanism for indirectly
accessing an object’s attributes and relationships using
string identifiers.
employee1.manager.directReports
[employee1 setValue:newArray forKey:@"employee1.manager.directReports"];
NSArray *reports = [employee1 valueForKey:@"employee1.manager.directReports"];
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 27
Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.
@interface MXParallaxView : UIView
@property (nonatomic,weak) MXParallaxHeader *parent;
@end
static void * const kMXParallaxHeaderKVOContext = (void*)&kMXParallaxHeaderKVOContext;
- (void)didMoveToSuperview
{
[self.superview addObserver:self.parent forKeyPath:NSStringFromSelector(@selector(contentOffset)) options:NSKeyValueObservingOptionNew context:kMXParallaxHeaderKVOContext];
}
//This is where the magic happens...
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == kMXParallaxHeaderKVOContext)
{
if ([keyPath isEqualToString:NSStringFromSelector(@selector(contentOffset))])
{
}
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
Key-Value Observing
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 28
objc.h
Objective-C Runtime
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
struct objc_class {
Class isa;
};
typedef struct objc_selector *SEL;
typedef struct objc_method *Method;
typedef struct objc_ivar *Ivar;
typedef struct objc_category *Category;
typedef struct objc_property *objc_property_t;
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 29
Runtime library functions
Objective-C Runtime
● Class manipulation: class_addMethod, class_addIvar, class_replaceMethod.
● Creating new classes: class_allocateClassPair, class_registerClassPair.
● Introspection: class_getName, class_getSuperclass, class_getInstanceVariable, class_getProperty, class_copyMethodList, class_copyIvarList,
class_copyPropertyList.
- (NSString *)description {
NSMutableDictionary *propertyValues = [NSMutableDictionary dictionary];
unsigned int propertyCount;
objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
for (unsigned int i = 0; i < propertyCount; i++) {
char const *propertyName = property_getName(properties[i]);
const char *attr = property_getAttributes(properties[i]);
if (attr[1] == '@') {
NSString *selector = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
SEL sel = sel_registerName([selector UTF8String]);
NSObject * propertyValue = objc_msgSend(self, sel);
propertyValues[selector] = propertyValue.description;
}
}
free(properties);
return [NSString stringWithFormat:@"%@: %@", self.class, propertyValues];
}
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 30
Runtime library functions
Objective-C Runtime
● Object manipulation: objc_msgSend, objc_getClass, object_copy.
@implementation NSMutableArray (CO)
+ (void)load {
Method addObject = class_getInstanceMethod(self, @selector(addObject:));
Method logAddObject = class_getInstanceMethod(self, @selector(logAddObject:));
method_exchangeImplementations(addObject, logAddObject);
}
- (void)logAddObject:(id)aObject {
[self logAddObject:aObject];
}
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 31
Runtime library functions
Objective-C Runtime
● Working with associative links
@interface UITableView (Additions)
@property(nonatomic, strong) UIView *placeholderView;
@end
static char key;
@implementation UITableView (Additions)
-(void)setPlaceholderView:(UIView *)placeholderView {
objc_setAssociatedObject(self, &key, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(UIView *) placeholderView {
return objc_getAssociatedObject(self, &key);
}
@end
© 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 32
Thanks! Any questions, comments?
Alexander.Markevich@solarwinds.com
Q&A

More Related Content

PDF
Native code in Android applications
PPTX
Java script Techniques Part I
PDF
JDK Power Tools
PDF
Synthesizing API Usage Examples
PDF
Metaprogramming in JavaScript
PPTX
Java 7 & 8 New Features
PPT
Reversing JavaScript
PDF
Advanced javascript
Native code in Android applications
Java script Techniques Part I
JDK Power Tools
Synthesizing API Usage Examples
Metaprogramming in JavaScript
Java 7 & 8 New Features
Reversing JavaScript
Advanced javascript

What's hot (20)

PDF
Google Dart
PDF
"Node.js threads for I/O-bound tasks", Timur Shemsedinov
PDF
Java Script Best Practices
PDF
안드로이드 데이터 바인딩
PDF
Extending Node.js using C++
PDF
ADG Poznań - Kotlin for Android developers
PPTX
Club of anonimous developers "Refactoring: Legacy code"
PDF
How to build an AOP framework in ActionScript
ODP
Javascript
PDF
JavaScript 101
PDF
JavaScript Basics and Best Practices - CC FE & UX
PDF
Robots in Swift
PPTX
分散式系統
PDF
Thinking In Swift
PDF
Shared memory and multithreading in Node.js - Timur Shemsedinov - JSFest'19
PDF
A JIT Smalltalk VM written in itself
PDF
57200143 flash-action-script-quickref
PDF
NoSQL and JavaScript: a love story
PDF
Checking the Source SDK Project
PDF
Pythia Reloaded: An Intelligent Unit Testing-Based Code Grader for Education
Google Dart
"Node.js threads for I/O-bound tasks", Timur Shemsedinov
Java Script Best Practices
안드로이드 데이터 바인딩
Extending Node.js using C++
ADG Poznań - Kotlin for Android developers
Club of anonimous developers "Refactoring: Legacy code"
How to build an AOP framework in ActionScript
Javascript
JavaScript 101
JavaScript Basics and Best Practices - CC FE & UX
Robots in Swift
分散式系統
Thinking In Swift
Shared memory and multithreading in Node.js - Timur Shemsedinov - JSFest'19
A JIT Smalltalk VM written in itself
57200143 flash-action-script-quickref
NoSQL and JavaScript: a love story
Checking the Source SDK Project
Pythia Reloaded: An Intelligent Unit Testing-Based Code Grader for Education
Ad

Similar to From C++ to Objective-C (20)

PDF
Никита Корчагин - Programming Apple iOS with Objective-C
PPT
iOS Application Development
PDF
What Makes Objective C Dynamic?
PPT
Objective-C for iOS Application Development
PDF
PDF
Objective-C
PDF
Objective c runtime
PPTX
Introduction to Objective - C
PPT
Objective c intro (1)
PDF
Intro to Objective C
KEY
Runtime
PDF
Pavel kravchenko obj c runtime
PPTX
Ios fundamentals with ObjectiveC
PDF
Objective-C Is Not Java
PPTX
iOS development introduction
PPTX
Presentation 1st
PDF
Programming with Objective-C
PPTX
Objective-c for Java Developers
PPTX
iOS,From Development to Distribution
PPTX
Objective-c Runtime
Никита Корчагин - Programming Apple iOS with Objective-C
iOS Application Development
What Makes Objective C Dynamic?
Objective-C for iOS Application Development
Objective-C
Objective c runtime
Introduction to Objective - C
Objective c intro (1)
Intro to Objective C
Runtime
Pavel kravchenko obj c runtime
Ios fundamentals with ObjectiveC
Objective-C Is Not Java
iOS development introduction
Presentation 1st
Programming with Objective-C
Objective-c for Java Developers
iOS,From Development to Distribution
Objective-c Runtime
Ad

More from corehard_by (20)

PPTX
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
PPTX
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
PDF
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
PPTX
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
PPTX
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
PPTX
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
PPTX
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
PPTX
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
PPTX
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
PPTX
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
PDF
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
PPTX
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
PPTX
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
PDF
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
PDF
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
PDF
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
PDF
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
PPTX
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
PDF
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
PDF
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019

Recently uploaded (20)

PPTX
A Presentation on Artificial Intelligence
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Machine learning based COVID-19 study performance prediction
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
MYSQL Presentation for SQL database connectivity
PDF
NewMind AI Monthly Chronicles - July 2025
PPTX
Big Data Technologies - Introduction.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Electronic commerce courselecture one. Pdf
A Presentation on Artificial Intelligence
Digital-Transformation-Roadmap-for-Companies.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Mobile App Security Testing_ A Comprehensive Guide.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Machine learning based COVID-19 study performance prediction
Per capita expenditure prediction using model stacking based on satellite ima...
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Review of recent advances in non-invasive hemoglobin estimation
Network Security Unit 5.pdf for BCA BBA.
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Diabetes mellitus diagnosis method based random forest with bat algorithm
MYSQL Presentation for SQL database connectivity
NewMind AI Monthly Chronicles - July 2025
Big Data Technologies - Introduction.pptx
Chapter 3 Spatial Domain Image Processing.pdf
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Electronic commerce courselecture one. Pdf

From C++ to Objective-C

  • 1. From C++ to Objective-C This document is designed to act as a bridge between C++ and Objective-C.
  • 2. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 1 Why Objective-C? #import "AppDelegate.h" #import <ScriptingBridge/ScriptingBridge.h> #import <objc/runtime.h> NSString * const TerminalNotifierBundleID = @"fr.julienxx.oss.terminal-notifier"; NSString * const NotificationCenterUIBundleID = @"com.apple.notificationcenterui"; NSString *_fakeBundleIdentifier = nil; @implementation NSBundle (FakeBundleIdentifier) - (NSString *)__bundleIdentifier; { if (self == [NSBundle mainBundle]) { return _fakeBundleIdentifier ? _fakeBundleIdentifier : TerminalNotifierBundleID; } else { return [self __bundleIdentifier]; } } @end
  • 3. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 2 A short history of Objective-C Timeline of Java, C, C#, C++ and Objective-C
  • 4. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 3 C++ Objective-C Syntax overview //In file Foo.h #pragma once //compilation guard class Foo { ... }; //In file Foo.cpp #include "Foo.h" ... //In file Foo.h //class declaration, different from //the "interface" Java keyword @interface Foo : NSObject { ... } @end //In file Foo.m #import "Foo.h" @implementation Foo ... @end
  • 5. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 4 C++ Objective-C Syntax overview class Foo { double x; public: int f(int x); float g(int x, int y); }; int Foo::f(int x) {...} float Foo::g(int x, int y) {...} @interface Foo : NSObject { double x; } -(int) f:(int)x; -(float) g:(int)x :(int)y; @end @implementation Foo -(int) f:(int)x {...} -(float) g:(int)x :(int)y {...} @end
  • 6. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 5 C++ Objective-C Syntax overview class Foo { public: int x; int apple(); protected: int y; int pear(); private: int z; int banana(); }; @interface Foo : NSObject { @public int x; @protected int y; @private int z; } -(int) apple; -(int) pear; -(int) banana; @end
  • 7. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 6 Root class, type id, nil and Nil values Unlike C++, Objective-C defines a root class. Every new class should be a descendant of the root class. In Cocoa, that class is NSObject, and it provides a huge number of facilities for the run-time system. OBJC_ROOT_CLASS @interface NSObject <NSObject> { Class isa OBJC_ISA_AVAILABILITY; } + (void)load; + (void)initialize; - (instancetype)init + (instancetype)new OBJC_SWIFT_UNAVAILABLE("use object initializers instead"); + (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead"); + (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead"); - (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer"); - (void)finalize OBJC_DEPRECATED("Objective-C garbage collection is no longer supported"); - (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE(""); - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""); + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("") + (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); + (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); + (NSUInteger)hash; + (Class)superclass; + (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead"); + (NSString *)description; + (NSString *)debugDescription; @end
  • 8. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 7 Root class, type id, nil and Nil values “id” is a data type of object identifiers in Objective-C, which can be use for an object of any type no matter what class does it have. “id” is the final supertype of all objects. By default, it is legal to send a message (call a method) to nil. The message is just ignored. The code can be greatly simplified by reducing the number of tests usually made with the null pointer. NSString *name = @"dobegin"; id data = name; NSURL *site = data; NSString *host = site.host; // oops! runtime error! // "unrecognized selector sent to instance" #if !defined(nil) #define nil (id)0 #endif // For example, this expression... if (name != nil && [name isEqualToString:@"Steve"]) { ... } // ...can be simplified to: if ([name isEqualToString:@"Steve"]) { ... } #if !defined(Nil) #define Nil (Class)0 #endif #inlcude <objc/runtime.h> Class foo = objc_allocateClassPair([NSString class], "NSDictionary", 0); if (foo != Nil) { }
  • 9. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 8 Messages and transmission A message is the name of a method, and any parameters associated with it, that are sent to, and executed by, an object. To get an object to do something, you send it a message telling it to apply a method. ● Search the class’s method cache for the IMP ● If not found, search the class hierarchy for the IMP ● Jump to IMP if found (jmp assembly instruction) ● If not found, jump to _objc_msgforward ● All objects can forward messages they don’t respond id objc_msgSend(id receiver, SEL method, ...); [receiver аddObject: otherObject]; objc_msgSend(receiver, 12, otherObject); addObject(receiver, otherObject);
  • 10. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 9 Messages and transmission In C++, code cannot be compiled if a method is called on an object that does not implement it. In Objective-C, there’s a difference: one can always send a message to an object. If it can’t be handled at run-time, it will be ignored (and raise an exception); moreover, instead of ignoring it, it can forward the message to another object. -(void) forwardInvocation:(NSInvocation*)anInvocation { //if we are here, that is because the object cannot handle //the message of the invocation //the bad selector can be obtained by sending "selector" //to the object "anInvocation" if ([anotherObject respondsToSelector:[anInvocation selector]]) [anInvocation invokeWithTarget:anotherObject]; else //do not forget to try with the superclass [super forwardInvocation:anInvocation]; }
  • 11. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 10 Messages and transmission Delegation is common with user interface elements in Cocoa (tables, outlines. . . ), taking advantage of the ability to send a message to an unknown object. An object can, for example, delegate some tasks to an assistant. -(void) performHardWork:(id)task { if ([assistant respondsToSelector:@selector(performHardWork:)]) [assistant performHardWork:task]; else [self findAnotherAssistant]; }
  • 12. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 11 Protocols A formal protocol is a set of methods that must be implemented in any conforming class. This can be seen as a certification regarding a class, ensuring that it is able to handle everything that is necessary for a given service. A class can conform to an unlimited number of protocols. @protocol NSObject - (BOOL)isEqual:(id)object; @property (readonly) NSUInteger hash; @property (readonly) Class superclass; - (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead"); - (instancetype)self; - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; - (BOOL)isProxy; - (BOOL)isKindOfClass:(Class)aClass; - (BOOL)isMemberOfClass:(Class)aClass; - (BOOL)conformsToProtocol:(Protocol *)aProtocol; - (BOOL)respondsToSelector:(SEL)aSelector; - (instancetype)retain OBJC_ARC_UNAVAILABLE; - (oneway void)release OBJC_ARC_UNAVAILABLE; - (instancetype)autorelease OBJC_ARC_UNAVAILABLE; - (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE; - (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE; @property (readonly, copy) NSString *description; @optional @property (readonly, copy) NSString *debugDescription; @end
  • 13. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 12 Class categories @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> @property (readonly) NSUInteger count; - (ObjectType)objectAtIndex:(NSUInteger)index; - (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithObjects:(const ObjectType _Nonnull [_Nullable])objects count:(NSUInteger)cnt NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; @end @interface NSArray(NSArrayCreation) + (instancetype)array; + (instancetype)arrayWithObject:(ObjectType)anObject; + (instancetype)arrayWithObjects:(const ObjectType _Nonnull [_Nonnull])objects count:(NSUInteger)cnt; + (instancetype)arrayWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION; + (instancetype)arrayWithArray:(NSArray<ObjectType> *)array; - (instancetype)initWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION; - (instancetype)initWithArray:(NSArray<ObjectType> *)array; - (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag; /* Reads array stored in NSPropertyList format from the specified url. */ - (nullable NSArray<ObjectType> *)initWithContentsOfURL:(NSURL *)url error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0)); /* Reads array stored in NSPropertyList format from the specified url. */ + (nullable NSArray<ObjectType> *)arrayWithContentsOfURL:(NSURL *)url error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0)) NS_SWIFT_UNAVAILABLE("Use initializer instead"); @end
  • 14. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 13 Properties The notion of property can be met when defining classes. The keyword @property can be associated to a data member, to tell how the accessors can be automatically generated by the compiler. It aims at writing less code and save some development time. A property is declared according to the following template : @property type name; or @property(attributes) type name; If they are not given, the attributes have a default value; otherwise, they can be redefined to answer the questions stated in the previous section. They can be : ● readwrite (default) or readonly to tell if the property should have both getter/setter or only the getter; ● assign (default), retain or copy, to tell how the value is stored internally; ● nonatomic to prevent thread-safety guards to be generated. They are generated by default (atomic). ● getter=..., setter=... to change the default name of the accessors. @property (copy, nonatomic, nonnull) NSString *foo; @property (copy, nonatomic, nonnull) NSString *str; @property (strong, nonatomic, nullable) NSNumber *bar; @property (copy, nonatomic, null_resettable) NSString *baz;
  • 15. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 14 Working with Blocks Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed. As a local variable: returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; As a property: @property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes); As a method parameter: - (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName; As an argument to a method call: [someObject someMethodThatTakesABlock:^returnType (parameters) {...}]; As a typedef: typedef returnType (^TypeName)(parameterTypes); TypeName blockName = ^returnType(parameters) {...};
  • 16. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 15 Working with Blocks By default blocks are created on the stack. Meaning they only exist in the scope they have been created in. //property @property (nonatomic, copy) SomeBlockType someBlock; //local variable someBlockType someBlock = ^{ NSLog(@"hi"); }; [someArray addObject:[someBlock copy]]; Blocks capture values from the enclosing scope. __weak SomeObjectClass *weakSelf = self; SomeBlockType someBlock = ^{ SomeObjectClass *strongSelf = weakSelf; if (strongSelf) { [strongSelf someMethod]; } };
  • 17. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 16 Working with Blocks Use __block Variables to Share Storage If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration. This means that the variable lives in storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. __block int anInteger = 42; void (^testBlock)(void) = ^{ NSLog(@"Integer is: %i", anInteger); anInteger = 100; }; testBlock(); NSLog(@"Value of original variable is now: %i", anInteger);
  • 18. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 17 Memory management
  • 19. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 18 Basic Memory Management Rules Memory management The memory management model is based on object ownership. Any object may have one or more owners. As long as an object has at least one owner, it continues to exist. If an object has no owners, the runtime system destroys it automatically. To make sure it is clear when you own an object and when you do not, Cocoa sets the following policy: ● You own any object you create You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”. ● You can take ownership of an object using retain A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation. ● When you no longer need it, you must relinquish ownership of an object you own You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object. ● You must not relinquish ownership of an object you do not own This is just corollary of the previous policy rules, stated explicitly.
  • 20. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 19 NSAutoreleasePool Memory management An object that supports Cocoa’s reference-counted memory management system. An autorelease pool stores objects that are sent a release message when the pool itself is drained. NSAutoreleasePool object contains objects that have received an autorelease message and when drained it sends a release message to each of those objects. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is drained (it may be longer if the object is subsequently retained). An object can be put into the same pool several times, in which case it receives a release message for each time it was put into the pool. @autoreleasepool { // Code that creates autoreleased objects. } Like any other code block, autorelease pool blocks can be nested: @autoreleasepool { // . . . @autoreleasepool { // . . . } . . . }
  • 21. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 20 NSAutoreleasePool Memory management Use local autorelease pool blocks to reduce peak memory footprint: NSArray *urls = <# An array of file URLs #>; for (NSURL *url in urls) { @autoreleasepool { NSError *error; NSString *fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; /* Process the string, creating and autoreleasing more objects. */ } }
  • 22. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 21 Grand Central Dispatch Multithreading Grand Central Dispatch (GCD) is a technology developed by Apple Inc. to optimize application support for systems with multi-core processors and other symmetric multiprocessing systems. It is an implementation of task parallelism based on the thread pool pattern. ● Dispatch Queues are objects that maintain a queue of tasks, either anonymous code blocks or functions, and execute these tasks in their turn. The library automatically creates several queues with different priority levels that execute several tasks concurrently, selecting the optimal number of tasks to run based on the operating environment. A client to the library may also create any number of serial queues, which execute tasks in the order they are submitted, one at a time - (IBAction)analyzeDocument:(NSButton *)sender { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSDictionary *stats = [myDoc analyze]; dispatch_async(dispatch_get_main_queue(), ^{ [myModel setDict:stats]; [myStatsView setNeedsDisplay:YES]; }); }); }
  • 23. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 22 Grand Central Dispatch ● Dispatch Sources are objects that allow the client to register blocks or functions to execute asynchronously upon system events, such as a socket or file descriptor being ready for reading or writing, or a POSIX signal. dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64_t leeway, dispatch_queue_t queue, dispatch_block_t block) { dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); if (timer) { dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway); dispatch_source_set_event_handler(timer, block); dispatch_resume(timer); } return timer; } Multithreading
  • 24. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 23 Grand Central Dispatch ● Dispatch Groups are objects that allow several tasks to be grouped for later joining. Tasks can be added to a queue as a member of a group, and then the client can use the group object to wait until all of the tasks in that group have completed. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); // Add a task to the group dispatch_group_async(group, queue, ^{ // Some asynchronous work }); // Do some other work while the tasks execute. // When you cannot make any more forward progress, // wait on the group to block the current thread. dispatch_group_wait(group, DISPATCH_TIME_FOREVER); // Release the group when it is no longer needed. dispatch_release(group); Multithreading
  • 25. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 24 Grand Central Dispatch ● Dispatch Semaphores are objects that allow a client to permit only a certain number of tasks to execute concurrently. // Create the semaphore, specifying the initial pool size dispatch_semaphore_t fd_sema = dispatch_semaphore_create(getdtablesize() / 2); // Wait for a free file descriptor dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER); fd = open("/etc/services", O_RDONLY); // Release the file descriptor when done close(fd); dispatch_semaphore_signal(fd_sema); Multithreading
  • 26. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 25 Grand Central Dispatch ● Create singleton using GCD's dispatch_once + (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } Multithreading
  • 27. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 26 Key-Value Coding Key-value coding is a mechanism for indirectly accessing an object’s attributes and relationships using string identifiers. employee1.manager.directReports [employee1 setValue:newArray forKey:@"employee1.manager.directReports"]; NSArray *reports = [employee1 valueForKey:@"employee1.manager.directReports"];
  • 28. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 27 Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. @interface MXParallaxView : UIView @property (nonatomic,weak) MXParallaxHeader *parent; @end static void * const kMXParallaxHeaderKVOContext = (void*)&kMXParallaxHeaderKVOContext; - (void)didMoveToSuperview { [self.superview addObserver:self.parent forKeyPath:NSStringFromSelector(@selector(contentOffset)) options:NSKeyValueObservingOptionNew context:kMXParallaxHeaderKVOContext]; } //This is where the magic happens... - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == kMXParallaxHeaderKVOContext) { if ([keyPath isEqualToString:NSStringFromSelector(@selector(contentOffset))]) { } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } Key-Value Observing
  • 29. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 28 objc.h Objective-C Runtime typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id; struct objc_class { Class isa; }; typedef struct objc_selector *SEL; typedef struct objc_method *Method; typedef struct objc_ivar *Ivar; typedef struct objc_category *Category; typedef struct objc_property *objc_property_t;
  • 30. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 29 Runtime library functions Objective-C Runtime ● Class manipulation: class_addMethod, class_addIvar, class_replaceMethod. ● Creating new classes: class_allocateClassPair, class_registerClassPair. ● Introspection: class_getName, class_getSuperclass, class_getInstanceVariable, class_getProperty, class_copyMethodList, class_copyIvarList, class_copyPropertyList. - (NSString *)description { NSMutableDictionary *propertyValues = [NSMutableDictionary dictionary]; unsigned int propertyCount; objc_property_t *properties = class_copyPropertyList([self class], &propertyCount); for (unsigned int i = 0; i < propertyCount; i++) { char const *propertyName = property_getName(properties[i]); const char *attr = property_getAttributes(properties[i]); if (attr[1] == '@') { NSString *selector = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]; SEL sel = sel_registerName([selector UTF8String]); NSObject * propertyValue = objc_msgSend(self, sel); propertyValues[selector] = propertyValue.description; } } free(properties); return [NSString stringWithFormat:@"%@: %@", self.class, propertyValues]; }
  • 31. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 30 Runtime library functions Objective-C Runtime ● Object manipulation: objc_msgSend, objc_getClass, object_copy. @implementation NSMutableArray (CO) + (void)load { Method addObject = class_getInstanceMethod(self, @selector(addObject:)); Method logAddObject = class_getInstanceMethod(self, @selector(logAddObject:)); method_exchangeImplementations(addObject, logAddObject); } - (void)logAddObject:(id)aObject { [self logAddObject:aObject]; } @end
  • 32. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 31 Runtime library functions Objective-C Runtime ● Working with associative links @interface UITableView (Additions) @property(nonatomic, strong) UIView *placeholderView; @end static char key; @implementation UITableView (Additions) -(void)setPlaceholderView:(UIView *)placeholderView { objc_setAssociatedObject(self, &key, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(UIView *) placeholderView { return objc_getAssociatedObject(self, &key); } @end
  • 33. © 2018 SolarWinds MSP Canada ULC and UK Ltd. All rights reserved. 32 Thanks! Any questions, comments? Alexander.Markevich@solarwinds.com Q&A