SlideShare a Scribd company logo
Swift & Objective-C
* “Using Swift with Cocoa and Objective-C” / .
Interoperability
Interacting with Objective-C APIs
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame
style:(UITableViewStyle)style;
init() { /* ... */ }
init(frame: CGRect, style: UITableViewStyle) { /* ... */ }
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero
style:UITableViewStyleGrouped];
let myTableView: UITableView = UITableView(frame: .zero, style: .grouped)
let myTextField = UITextField(frame: CGRect(x: 0.0, y: 0.0,
width: 200.0, height: 40.0))
Initialization
• Objective-C
• Swift
Interacting with Objective-C APIs
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)
Convenience Initializers
• Objective-C
• Swift
To be used with the same syntax as initializers.
Interacting with Objective-C APIs
if let image = UIImage(contentsOfFile: "MyImage.png") {
// loaded the image successfully
} else {
// could not load the image
}
Failable Initialization
• Objective-C
• Swift
Initializers directly return the object they initialize. To inform the caller when
initialization has failed, an Objective-C initializer can return nil.
Interacting with Objective-C APIs
Nullability Properties
• Swift
• Objective-C @property (nullable) id nullableProperty;
@property (nonnull) id nonNullProperty;
@property id unannotatedProperty;
NS_ASSUME_NONNULL_BEGIN
- (id)returnsNonNullValue;
- (void)takesNonNullParameter:(id)value;
NS_ASSUME_NONNULL_END
- (nullable id)returnsNullableValue;
- (void)takesNullableParameter:(nullable id)value;
- (id)returnsUnannotatedValue;
- (void)takesUnannotatedParameter:(id)value;
var nullableProperty: Any?
var nonNullProperty: Any
var unannotatedProperty: Any!
func returnsNonNullValue() -> Any
func takesNonNullParameter(value: Any)
func returnsNullableValue() -> Any?
func takesNullableParameter(value: Any?)
func returnsUnannotatedValue() -> Any!
func takesUnannotatedParameter(value: Any!)
Interacting with Objective-C APIs
Accessing Properties
• readonly = computed property { get }
• weak = weak (weak var)
• assign, copy, strong, unsafe_unretained
• Class = Type
• Atomic
• Accessor (getter= / setter=)
Interacting with Objective-C APIs
myTableView.insertSubview(mySubview, at: 2)
Working with Methods
• Objective-C
• Swift
[myTableView insertSubview:mySubview atIndex:2];
myTableView.layoutIfNeeded()
Can call Objective-C methods from Swift using dot syntax.
Interacting with Objective-C APIs
var x: Any = "hello" as String
x as? String // String with value "hello"
x as? NSString // NSString with value "hello"
x = "goodbye" as NSString
x as? String // String with value "goodbye"
x as? NSString // NSString with value "goodbye"
id
• Objective-C
• Swift
The Objective-C id type is imported by Swift as the Any type.
Interacting with Objective-C APIs
let userDefaults = UserDefaults.standard
let lastRefreshDate = userDefaults.object(forKey: "LastRefreshDate")
// lastRefreshDate is of type Any?
if let date = lastRefreshDate as? Date {
print("(date.timeIntervalSinceReferenceDate)")
}
Downcasting Any
let myDate = lastRefreshDate as! Date
let timeInterval = myDate.timeIntervalSinceReferenceDate
let myDate = lastRefreshDate as! String // Error
Forced downcast operator (as!)
Forced downcast error
Conditional type cast operator (as?)
Interacting with Objective-C APIs
var myObject: AnyObject = UITableViewCell()
myObject = NSDate()
let futureDate = myObject.addingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow
Dynamic Method Lookup & Optional chaining
AnyObject type lookup @objc method dynamically
myObject.character(at: 5)
// crash, myObject doesn't respond to that method
let myCount = myObject.count
// myCount has Int? type and nil value
let myChar = myObject.character?(at: 5)
// myChar has unichar? type and nil value
if let fifthCharacter = myObject.character?(at: 5) {
print("Found (fifthCharacter) at index 5")
}
// conditional branch not executed
Interacting with Objective-C APIs
Bridging Optionals to Nonnullable Objects
@implementation OptionalBridging
+ (void)logSomeValue:(nonnull id)valueFromSwift {
if ([valueFromSwift isKindOfClass: [NSNull class]]) {
os_log(OS_LOG_DEFAULT, "Received an NSNull value.");
} else {
os_log(OS_LOG_DEFAULT, "%s", [valueFromSwift UTF8String]);
}
}
@end
let someValue: String? = "Bridge me, please."
let nilValue: String? = nil
OptionalBridging.logSomeValue(someValue as Any) // String
OptionalBridging.logSomeValue(nilValue as Any) // an NSNull value.
Optional nil NSNull ,
Optional unwrapped value [T?] => NSArray<T>
Interacting with Objective-C APIs
Lightweight Generics
@property NSArray<NSDate *> *dates;
@property NSCache<NSObject *, id<NSDiscardableContent>> *cachedData;
@property NSDictionary <NSString *, NSArray<NSLocale *>> *supportedLocales;
var dates: [Date]
var cachedData: NSCache<AnyObject, NSDiscardableContent>
var supportedLocales: [String: [Locale]]
• Objective-C
• Swift
Interacting with Objective-C APIs
Generic Class
@interface List<T: id<NSCopying>> : NSObject
- (List<T> *)listByAppendingItemsInList:(List<T> *)otherList;
@end
@interface ListContainer : NSObject
- (List<NSValue *> *)listOfValues;
@end
@interface ListContainer (ObjectList)
- (List *)listOfObjects;
@end
• Objective-C
• Swift class List<T: NSCopying> : NSObject {
func listByAppendingItemsInList(otherList: List<T>) -> List<T>
}
class ListContainer : NSObject {
func listOfValues() -> List<NSValue>
}
extension ListContainer {
func listOfObjects() -> List<NSCopying>
}
Interacting with Objective-C APIs
Extensions (of existing classes, structures…)
extension UIBezierPath {
convenience init(triangleSideLength: CGFloat, origin: CGPoint) {
self.init()
let squareRoot = CGFloat(sqrt(3.0))
let altitude = (squareRoot * triangleSideLength) / 2
move(to: origin)
addLine(to: CGPoint(x: origin.x + triangleSideLength, y: origin.y))
addLine(to: CGPoint(x: origin.x + triangleSideLength / 2, y: origin.y + altitude))
close()
}
}
• Swift
Interacting with Objective-C APIs
Closures & Blocks
void (^completionBlock)(NSData *) = ^(NSData *data) {
// ...
}
• Swift
• Objective-C
let completionBlock: (Data) -> Void = { data in
// ...
}
__weak typeof(self) weakSelf = self;
self.block = ^{
__strong typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
};
self.closure = { [unowned self] in
self.doSomething()
}
Interacting with Objective-C APIs
Object Comparison
• Swift
• Objective-C
equality : ( -isEqual: )
identity :
equality (==) : (Equatable )
== Operator isEqual:
isEqual:
identity (===) :
=== Operator
Interacting with Objective-C APIs
Hashing
• Swift
• Objective-C
@property NSDictionary *unqualifiedDictionary;
@property NSDictionary<NSString *, NSDate *> *qualifiedDictionary;
@property NSSet *unqualifiedSet;
@property NSSet<NSString *> *qualifiedSet;
var unqualifiedDictionary: [AnyHashable: Any]
var qualifiedDictionary: [String: Date]
var unqualifiedSet: Set<AnyHashable>
var qualifiedSet: Set<String>
Interacting with Objective-C APIs
Excludes Swift-only
• Generics
• Tuples
• Enumerations defined in Swift without Int raw value type
• Structures defined in Swift
• Top-level functions defined in Swift
• Global variables defined in Swift
• Typealiases defined in Swift
• Swift-style variadics
• Nested types
• Curried functions
Interacting with Objective-C APIs
Swift Type Compatibility
class Jukebox: NSObject {
var library: Set<String>
var nowPlaying: String?
var isCurrentlyPlaying: Bool {
return nowPlaying != nil
}
class var favoritesPlaylist: [String] {
// return an array of song names
}
init(songs: String...) {
self.library = Set<String>(songs)
}
func playSong(named name: String) throws {
// play song or throw an error if unavailable
}
}
@interface Jukebox : NSObject
@property (nonatomic, strong, nonnull) NSSet<NSString *> *library;
@property (nonatomic, copy, nullable) NSString *nowPlaying;
@property (nonatomic, readonly, getter=isCurrentlyPlaying) BOOL currentlyPlaying;
@property (nonatomic, class, readonly, nonnull) NSArray<NSString *> * favoritesPlaylist;
- (nonnull instancetype)initWithSongs:(NSArray<NSString *> * __nonnull)songs
OBJC_DESIGNATED_INITIALIZER;
- (BOOL)playSong:(NSString * __nonnull)name
error:(NSError * __nullable * __null_unspecified)error;
@end
Interacting with Objective-C APIs
Configuring Swift Interfaces
@objc(Color)
enum Цвет: Int {
@objc(Red)
case Красный
@objc(Black)
case Черный
}
@objc(Squirrel)
class Белка: NSObject {
@objc(color)
var цвет: Цвет = .Красный
@objc(initWithName:)
init (имя: String) {
// ...
}
@objc(hideNuts:inTree:)
func прячьОрехи(количество: Int, вДереве дерево: Дерево) {
// ...
}
}
Interacting with Objective-C APIs
Selectors
import UIKit
class MyViewController: UIViewController {
let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
override init?(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
let action = #selector(MyViewController.tappedButton)
myButton.addTarget(self, action: action, forControlEvents: .touchUpInside)
}
func tappedButton(sender: UIButton?) {
print("tapped button")
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
Interacting with Objective-C APIs
Unsafe Invocation of Objective-C Methods
let string: NSString = "Hello, Cocoa!"
let selector = #selector(NSString.lowercased(with:))
let locale = Locale.current
if let result = string.perform(selector, with: locale) {
print(result.takeUnretainedValue())
}
// Prints "hello, cocoa!"
let array: NSArray = ["delta", "alpha", "zulu"]
// Not a compile-time error because NSDictionary has this selector.
let selector = #selector(NSDictionary.allKeysForObject)
// Raises an exception because NSArray does not respond to this selector.
array.perform(selector)
Perform Selector
Unsafe invocation
Interacting with Objective-C APIs
Keys & Key Paths
class Person: NSObject {
var name: String
var friends: [Person] = []
var bestFriend: Person? = nil
init(name: String) {
self.name = name
}
}
let gabrielle = Person(name: "Gabrielle")
let jim = Person(name: "Jim")
let yuanyuan = Person(name: "Yuanyuan")
gabrielle.friends = [jim, yuanyuan]
gabrielle.bestFriend = yuanyuan
#keyPath(Person.name)
// "name"
gabrielle.value(forKey: #keyPath(Person.name))
// "Gabrielle"
#keyPath(Person.bestFriend.name)
// "bestFriend.name"
gabrielle.value(forKeyPath: #keyPath(Person.bestFriend.name))
// "Yuanyuan"
#keyPath(Person.friends.name)
// "friends.name"
gabrielle.value(forKeyPath: #keyPath(Person.friends.name))
// ["Yuanyuan", "Jim"]
Objective-C Behavior
Inheriting from Objective-C Classes
@IBDesignable, @IBInpectable
let myPersonClass: AnyClass? = NSClassFromString("MyGreatApp.Person")
Working with Cocoa Frameworks
Foundation
Working with Cocoa Frameworks
Core Foundation
CFStringRef StringByAddingTwoStrings(CFStringRef s1, CFStringRef s2)
func StringByAddingTwoStrings(_: CFString!, _: CFString!) -> Unmanaged<CFString>! {
// ...
}
let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
CFTypeRef remaps to the AnyObject
CFStringRef remaps to the CFString class
takeRetainedValue()
Working with Cocoa Frameworks
Unified Logging
import os.log
os_log("This is a log message.”)
let fileSize = 1234567890
os_log("Finished downloading file. Size: %{iec-bytes}d", fileSize)
os_log("This is additional info that may be helpful for troubleshooting.", type: .info)
let customLog = OSLog("com.your_company.your_subsystem_name.plist", "your_category_name")
os_log("This is info that may be helpful during development or debugging.",
log: customLog, type: .debug)
Working with Cocoa Frameworks
Cocoa structure
NSValue
MKCoordinateSpan
NSRange
CLLocationCoordinate2D
CATransform3D, CGAffineTransform
CGPoint, CGRect, CGSize, CGVector
CMTimeMapping, CMTimeRange, CMTime
SCNMatrix4, SCNVector3, SCNVector4
UIEdgeInsets, UIOffset
NSValue
Adopting Cocoa Design Patterns
Delegation
1)Check that myDelegate is not nil.
2)Check that myDelegate implements the method
window:willUseFullScreenContentSize:.
3)If 1 and 2 hold true, invoke the method and assign the result of the method
to the value named fullScreenSize.
4)Print the return value of the method.
class MyDelegate: NSObject, NSWindowDelegate {
func window(_ window: NSWindow, willUseFullScreenContentSize proposedSize: NSSize) -> NSSize {
return proposedSize
}
}
//…
myWindow.delegate = MyDelegate()
if let fullScreenSize = myWindow.delegate?.window(myWindow, willUseFullScreenContentSize: mySize) {
print(NSStringFromSize(fullScreenSize))
}
Adopting Cocoa Design Patterns
Lazy Initialization
@property NSXMLDocument *XML;
- (NSXMLDocument *)XML {
if (_XML == nil) {
_XML = [[NSXMLDocument alloc] initWithContentsOfURL:[[Bundle mainBundle]
URLForResource:@"/path/to/resource" withExtension:@"xml"] options:0 error:nil];
}
return _XML;
}
lazy var XML: XMLDocument = try! XMLDocument(contentsOf:
Bundle.main.url(forResource: "document", withExtension: "xml")!, options: 0)
• Objective-C
• Swift
Adopting Cocoa Design Patterns
Lazy property
var pattern: String
lazy var regex: NSRegularExpression = try! NSRegularExpression(pattern: self.pattern,
options: [])
lazy var currencyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencySymbol = "¤"
return formatter
}()
• Swift
use self-evaluating closure
Adopting Cocoa Design Patterns
Error Handling
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *fromURL = [NSURL fileURLWithPath:@"/path/to/old"];
NSURL *toURL = [NSURL fileURLWithPath:@"/path/to/new"];
NSError *error = nil;
BOOL success = [fileManager moveItemAtURL:fromURL toURL:toURL error:&error];
if (!success) {
NSLog(@"Error: %@", error.domain);
}
• Swift
• Objective-C
let fileManager = FileManager.default
let fromURL = URL(fileURLWithPath: "/path/to/old")
let toURL = URL(fileURLWithPath: "/path/to/new")
do {
try fileManager.moveItem(at: fromURL, to: toURL)
} catch let error as NSError {
print("Error: (error.domain)")
}
Adopting Cocoa Design Patterns
Converting errors to Optional values
• Swift
• Objective-C
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *tmpURL = [fileManager URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
if (tmpURL != nil) {
// ...
}
let fileManager = FileManager.default
if let tmpURL = try? fileManager.url(for: .cachesDirectory, in: .userDomainMask,
appropriateFor: nil, create: true) {
// ...
}
Adopting Cocoa Design Patterns
Throwing error
• Swift
• Objective-C
// an error occurred
if (errorPtr) {
*errorPtr = [NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorCannotOpenFile
userInfo:nil];
}
// an error occurred
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)
Adopting Cocoa Design Patterns
Key-value Observing
KVO with a Swift class inherits from NSObject class
1) Add dynamic modifier to any property
2) Create a global context variable
3) Add an observer for the key-path, override the observeValue() method
and remove the observer in deinit.
class MyObjectToObserve: NSObject {
dynamic var myDate = NSDate()
func updateDate() {
myDate = NSDate()
}
}
private var myContext = 0
class MyObserver: NSObject {
var objectToObserve = MyObjectToObserve()
override init() {
super.init()
objectToObserve.addObserver(self, forKeyPath: #keyPath(MyObjectToObserve.myDate),
options: .new, context: &myContext)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change:
[NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &myContext {
if let newValue = change?[.newKey] { print("Date changed: (newValue)”) }
} else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
deinit {
objectToObserve.removeObserver(self, forKeyPath: #keyPath(MyObjectToObserve.myDate),
context: &myContext)
}
}
Adopting Cocoa Design Patterns
Undo architecture
Create an undo operation using an NSInvocation
@IBOutlet var remainingLabel: NSTextView!
func mark(task: Task, asCompleted completed: Bool) {
if let target = undoManager?.prepare(withInvocationTarget: self) as? ToDoListController {
target.mark(task: task, asCompleted: !completed)
undoManager?.setActionName(NSLocalizedString("todo.task.mark",
comment: "Mark As Completed"))
}
task.completed = completed
tableView.reloadData()
let numberRemaining = tasks.filter{ $0.completed }.count
remainingLabel.string = String(format: NSLocalizedString("todo.task.remaining",
comment: "Tasks Remaining: %d"), numberRemaining)
}
Adopting Cocoa Design Patterns
Singleton
initialization in a call the dispatch_once function
+ (instancetype)sharedInstance {
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
class Singleton {
static let sharedInstance = Singleton()
}
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
Adopting Cocoa Design Patterns
Introspection
use the isKindOfClass: method or conformsToProtocol: method
if object is UIButton {
// object is of type UIButton
} else {
// object is not of type UIButton
}
if let button = object as? UIButton {
// object is successfully cast to type UIButton and bound to button
} else {
// object could not be cast to type UIButton
}
if let dataSource = object as? UITableViewDataSource {
// object conforms to UITableViewDataSource and is bound to dataSource
} else {
// object not conform to UITableViewDataSource
}
• Swift
• Objective-C
Adopting Cocoa Design Patterns
Serialization
To encode and decode objects to and from architecture-independent representations.
Use NSJSONSerialization and NSPropertyListSerialization
import Foundation
import CoreLocation
struct Venue {
enum Category: String {
case entertainment
case food
case nightlife
case shopping
}
var name: String
var coordinates: CLLocationCoordinate2D
var category: Category
}
{
"name": "Caffè Macs",
"coordinates": {
"lat": 37.330576,
"lng": -122.029739
},
"category": "food"
}
Adopting Cocoa Design Patterns
Serialization : Initializer
init?(attributes: [String: Any]) {
guard let name = attributes["name"] as? String,
let coordinates = attributes["coordinates"] as? [String: Double],
let latitude = coordinates["lat"],
let longitude = coordinates["lng"],
let category = Category(rawValue: attributes["category"] as? String ?? "Invalid")
else {
return nil
}
self.name = name
self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
self.category = category
}
let JSON = "{"name": "Caffè Macs","coordinates": {"lat": 37.330576,"lng": -122.029739},
"category": "food"}"
let data = JSON.data(using: String.Encoding.utf8)!
let attributes = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let venue = Venue(attributes: attributes)!
print(venue.name)
// Prints "Caffè Macs"
Initialize with Dictionary<String, Any>
Create a Venue from a JSON representation
Adopting Cocoa Design Patterns
Serialization : Validating
enum ValidationError: Error {
case missing(String)
case invalid(String)
}
init(attributes: [String: Any]) throws {
guard let name = attributes["name"] as? String else {
throw ValidationError.missing("name")
}
guard let coordinates = attributes["coordinates"] as? [String: Double] else {
throw ValidationError.missing("coordinates")
}
guard let latitude = coordinates["lat"],
let longitude = coordinates["lng"]
else {
throw ValidationError.invalid("coordinates")
}
guard let categoryName = attributes["category"] as? String else {
throw ValidationError.missing("category")
}
guard let category = Category(rawValue: categoryName) else {
throw ValidationError.invalid("category")
}
self.name = name
self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
self.category = category
}
Adopting Cocoa Design Patterns
Localization
use NSLocalizedString, NSLocalizedStringFromTable,
NSLocalizedStringFromTableInBundle, NSLocalizedStringWithDefaultValue
• Objective-C
• Swift
A single function: NSLocalizedString(_:tableName:bundle:value:comment:)
let format = NSLocalizedString("Hello, %@!", comment: "Hello, {given name}!")
let name = "Mei"
let greeting = String(format: format, arguments: [name as CVarArg])
print(greeting)
// Prints "Hello, Mei!"
if let path = Bundle.main.path(forResource: "Localization", ofType: "strings",
inDirectory: nil, forLocalization: "ja"),
let bundle = Bundle(path: path) {
let translation = NSLocalizedString("Hello", bundle: bundle, comment: "")
print(translation)
}
// Prints " "
Adopting Cocoa Design Patterns
API Availability
use respondsToSelector: and instancesRespondToSelector: methods
• Objective-C
• Swift
let locationManager = CLLocationManager()
if #available(iOS 8.0, macOS 10.10, *) {
locationManager.requestWhenInUseAuthorization()
}
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {
// Method is available for use.
} else {
// Method is not available.
}
let locationManager = CLLocationManager()
guard #available(iOS 8.0, macOS 10.10, *) else { return }
locationManager.requestWhenInUseAuthorization()
Adopting Cocoa Design Patterns
Processing Command-Line Arguments
for argument in CommandLine.arguments {
print(argument)
}
// prints "/path/to/app"
// prints "--argumentName"
// prints "value"
$ /path/to/app --argumentName value
Interacting with C APIs
Primitive Types
C Type Swift Type
bool CBool
char, signed char CChar
unsigned char CUnsignedChar
short CShort
unsigned short CUnsignedShort
int CInt
unsigned int CUnsignedInt
long CLong
unsigned long CUnsignedLong
long long CLongLong
unsigned long long CUnsignedLongLong
wchar_t CWideChar
char16_t CChar16
char32_t CChar32
float CFloat
double CDouble
Interacting with C APIs
Importing Constant Enumerations and Structures
Annotate an typedef declaration with the NS_STRING_ENUM or
NS_EXTENSIBLE_STRING_ENUM
• Objective-C
• Swift
struct TrafficLightColor: RawRepresentable {
typealias RawValue = String
init(rawValue: RawValue)
var rawValue: RawValue { get }
static var red: TrafficLightColor { get }
static var yellow: TrafficLightColor { get }
static var green: TrafficLightColor { get }
}
typedef NSString * TrafficLightColor NS_STRING_ENUM;
TrafficLightColor const TrafficLightColorRed;
TrafficLightColor const TrafficLightColorYellow;
TrafficLightColor const TrafficLightColorGreen;
Interacting with C APIs
Functions
Any function declared in a C header as a Swift global function.
• Objective-C
• Swift
func product(_ multiplier: Int32, _ multiplicand: Int32) -> Int32
func quotient(_ dividend: Int32, _ divisor: Int32, _ remainder:
UnsafeMutablePointer<Int32>) -> Int32
func createPoint2D(_ x: Float, _ y: Float) -> Point2D
func distance(_ from: Point2D, _ to: Point2D) -> Float
int product(int multiplier, int multiplicand);
int quotient(int dividend, int divisor, int *remainder);
struct Point2D createPoint2D(float x, float y);
float distance(struct Point2D from, struct Point2D to);
Interacting with C APIs
Variadic Functions
Call C variadic functions, such as vasprintf, using the getVaList() or withVaList()
func swiftprintf(format: String, arguments: CVarArg...) -> String? {
return withVaList(arguments) { va_list in
var buffer: UnsafeMutablePointer<Int8>? = nil
return format.withCString { CString in
guard vasprintf(&buffer, CString, va_list) != 0 else {
return nil
}
return String(validatingUTF8: buffer!)
}
}
}
print(swiftprintf(format: "√2 ≅ %g", arguments: sqrt(2.0))!)
// Prints "√2 ≅ 1.41421"
Interacting with C APIs
Structures
Any C Structure declared in a C header as a Swift structure.
struct Color {
float r, g, b;
};
typedef struct Color Color;
public struct Color {
var r: Float
var g: Float
var b: Float
init()
init(r: Float, g: Float, b: Float)
}
• Swift
Interacting with C APIs
Importing Functions as Type Members
Use CF_SWIFT_NAME macro in you own code
Color ColorCreateWithCMYK(float c, float m, float y, float k) CF_SWIFT_NAME(Color.init(c:m:y:k:));
float ColorGetHue(Color color) CF_SWIFT_NAME(getter:Color.hue(self:));
void ColorSetHue(Color color, float hue) CF_SWIFT_NAME(setter:Color.hue(self:newValue:));
Color ColorDarkenColor(Color color, float amount) CF_SWIFT_NAME(Color.darken(self:amount:));
extern const Color ColorBondiBlue CF_SWIFT_NAME(Color.bondiBlue);
Color ColorGetCalibrationColor(void) CF_SWIFT_NAME(getter:Color.calibration());
Color ColorSetCalibrationColor(Color color) CF_SWIFT_NAME(setter:Color.calibration(newValue:));
extension Color {
init(c: Float, m: Float, y: Float, k: Float)
var hue: Float { get set }
func darken(amount: Float) -> Color
static var bondiBlue: Color
static var calibration: Color
}
• Swift
Interacting with C APIs
Enumerations
Any C enumeration marked with the NS_ENUM macro as a Swift Enumeration(Int)
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
enum UITableViewCellStyle: Int {
case `default`
case value1
case value2
case subtitle
}
• Swift
let cellStyle: UITableViewCellStyle = .default
Interacting with C APIs
Enumerations : Option Sets
Any C enumeration marked with the NS_OPTIONS macro as a Swift option set.
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
public struct UIViewAutoresizing : OptionSet {
public init(rawValue: UInt)
public static var flexibleLeftMargin: UIViewAutoresizing { get }
public static var flexibleWidth: UIViewAutoresizing { get }
public static var flexibleRightMargin: UIViewAutoresizing { get }
public static var flexibleTopMargin: UIViewAutoresizing { get }
public static var flexibleHeight: UIViewAutoresizing { get }
public static var flexibleBottomMargin: UIViewAutoresizing { get }
}
• Swift
Interacting with C APIs
Unions
Swift imports C unions as Swift structures, not support unions.
union SchroedingersCat {
bool isAlive;
bool isDead;
};
struct SchroedingersCat {
var isAlive: Bool { get set }
var isDead: Bool { get set }
init(isAlive: Bool)
init(isDead: Bool)
init()
}
• Swift
Interacting with C APIs
Unnamed Structure and Union Fields
C struct and union types can define fields that have no name or that are of an
unnamed type.
struct Cake {
union {
int layers;
double height;
};
struct {
bool icing;
bool sprinkles;
} toppings;
};
var simpleCake = Cake()
simpleCake.layers = 5
print(simpleCake.toppings.icing)
// Prints "false"
let cake = Cake(
.init(layers: 2),
toppings: .init(icing: true, sprinkles: false)
)
print("The cake has (cake.layers) layers.")
// Prints "The cake has 2 layers."
print("Does it have sprinkles?", cake.toppings.sprinkles ? "Yes." : "No.")
// Prints "Does it have sprinkles? No."
Interacting with C APIs
Pointers
C Syntax Swift Syntax
const Type * UnsafePointer<Type>
Type * UnsafeMutablePointer<Type>
C Syntax Swift Syntax
Type * const * UnsafePointer<Type>
Type * __strong * UnsafeMutablePointer<Type>
Type ** AutoreleasingUnsafeMutablePointer<Type>
C Syntax Swift Syntax
const void * UnsafePointer
void * UnsafeMutablePointer
For return types, variables, and arguments
For class types
For pointers to untyped, raw memory
Interacting with C APIs
Constant Pointers
func takesAPointer(_ p: UnsafePointer<Float>) {
// ...
}
var x: Float = 0.0
takesAPointer(&x)
takesAPointer([1.0, 2.0, 3.0])
var x: Float = 0.0, y: Int = 0
takesARawPointer(&x)
takesARawPointer(&y)
takesARawPointer([1.0, 2.0, 3.0] as [Float])
let intArray = [1, 2, 3]
takesARawPointer(intArray)
func takesARawPointer(_ p: UnsafeRawPointer?) {
// ...
}
Interacting with C APIs
Mutable Pointers
func takesAMutablePointer(_ p: UnsafeMutablePointer<Float>) {
// ...
}
var x: Float = 0.0
var a: [Float] = [1.0, 2.0, 3.0]
takesAMutablePointer(&x)
takesAMutablePointer(&a)
var x: Float = 0.0, y: Int = 0
var a: [Float] = [1.0, 2.0, 3.0], b: [Int] = [1, 2, 3]
takesAMutableRawPointer(&x)
takesAMutableRawPointer(&y)
takesAMutableRawPointer(&a)
takesAMutableRawPointer(&b)
func takesAMutableRawPointer(_ p: UnsafeMutableRawPointer?) {
// ...
}
Interacting with C APIs
Autoreleasing Pointers
func takesAnAutoreleasingPointer(_ p: AutoreleasingUnsafeMutablePointer<NSDate?>) {
// ...
}
var x: NSDate? = nil
takesAnAutoreleasingPointer(&x)
Interacting with C APIs
Function Pointers
func customCopyDescription(_ p: UnsafeRawPointer?) -> Unmanaged<CFString>? {
// return an Unmanaged<CFString>? value
}
var callbacks = CFArrayCallBacks(
version: 0,
retain: nil,
release: nil,
copyDescription: customCopyDescription,
equal: { (p1, p2) -> DarwinBoolean in
// return Bool value
}
)
var mutableArray = CFArrayCreateMutable(nil, 0, &callbacks)
C function pointers are imported into Swift as closures with C function pointer calling
convention, denoted by the @convention(c) attribute.
Interacting with C APIs
Buffer Pointers & Null Pointers
Buffer Pointers : Used for low-level access to a region of memory.
UnsafeBufferPointer
UnsafeMutableBufferPointer
UnsafeRawBufferPointer
UnsafeMutableRawBufferPointer
Objective-C Syntax Swift Syntax
const Type * _Nonnull UnsafePointer<Type>
const Type * _Nullable UnsafePointer<Type>?
const Type * _Null_unspecified UnsafePointer<Type>!
Null Pointers
Pointers Arithmatic
let pointer: UnsafePointer<Int8>
let offsetPointer = pointer + 24
// offsetPointer is 24 strides ahead of pointer
Interacting with C APIs
Data Type Size Calculation
In C, the sizeof and alignof operators return the size and alignment
In Swift, you use MemoryLayout<T> to access the memory layout of the
parameterized type T through the size, stride, and alignment properties.
print(MemoryLayout<timeval>.size)
// Prints "16"
print(MemoryLayout<timeval>.stride)
// Prints "16"
print(MemoryLayout<timeval>.alignment)
// Prints "8"
let sockfd = socket(AF_INET, SOCK_STREAM, 0)
var optval = timeval(tv_sec: 30, tv_usec: 0)
let optlen = socklen_t(MemoryLayout<timeval>.size)
if setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &optval, optlen) == 0 {
// ...
}
Interacting with C APIs
Preprocessor Directives
Simple Macro
Complex Macro, no counterpart in Swift
Conditional Compilation Blocks
#if DEBUG_LOGGING
print("Flag enabled.")
#endif
#define FADE_ANIMATION_DURATION 0.35 let FADE_ANIMATION_DURATION = 0.35
Function Valid arguments
os() macOS, iOS, watchOS, tvOS, Linux
arch() x86_64, arm, arm64, i386
swift() >= followed by a version number
#if arch(arm) || arch(arm64)
#if swift(>=3.0)
print("Using Swift 3 ARM code")
#else
print("Using Swift 2.2 ARM code")
#endif
#elseif arch(x86_64)
print("Using 64-bit x86 code.")
#else
print("Using general code.")
#endif
Mix & Match
Mix and Match Overview
Swift & Objective-C in the Same Project
Importing Objective-C into Swift
rely on an Objective-C bridging header to expose those files to Swift
{product module name} + "-Bridging-Header.h"
ex. = CodesquadApp CodesquadApp-Bridging-Header.h
To import Objective-C code into Swift from the same target
1) In your Objective-C bridging header file, import every Objective-C header
2) In Build Settings > Swift Compiler - Code Generation, make sure the Objective-C
Bridging Header build setting has a path to the bridging header file
Swift & Objective-C in the Same Project
Importing Swift into Objective-C
rely on an Xcode-generated header file to expose those files to Objective-C
{product module name} + "-Swift.h"
ex. = CodesquadApp CodesquadApp-Swift.h
The generated header contains interfaces for Swift declarations marked with the
public or open modifier.
An umbrella header for your Swift code
Marked with the internal modifier if your app target has bridging header.
To import Swift code into Objective-C from the same target
#import "ProductModuleName-Swift.h"
Swift & Objective-C in the Same Project
Importing External Frameworks
Swift code
import FrameworkName @import FrameworkName;
Objective-C code
Import into Swift Import into Objective-C
Any language
framework
import FrameworkName @import FrameworkName;
Swift & Objective-C in the Same Project
Using Swift from Objective-C
Swift class
MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
[swiftObject swiftMethod];
// MyObjcClass.h
@class MySwiftClass;
@protocol MySwiftProtocol;
@interface MyObjcClass : NSObject
- (MySwiftClass *)returnSwiftClassInstance;
- (id <MySwiftProtocol>)returnInstanceAdoptingSwiftProtocol;
// ...
@end
Referencing a Swift Class or Protocol in an Objective-C Header
Swift & Objective-C in the Same Project
Using Swift from Objective-C
Declaring a Swift Protocol That Can Be Adopted by an Objective-C Class
@objc public protocol MySwiftProtocol {
func requiredMethod()
@objc optional func optionalMethod()
}
// MyObjcClass.m
#import "ProductModuleName-Swift.h"
@interface MyObjcClass () <MySwiftProtocol>
// ...
@end
@implementation MyObjcClass
// ...
@end
Adopting a Swift Protocol in an Objective-C Implementation
Swift & Objective-C in the Same Project
Using Swift from Objective-C
Declaring a Swift Error Type That Can Be Used from Objective-C
@objc public enum CustomError: Int, Error {
case a, b, c
}
// Project-Swift.h
typedef SWIFT_ENUM(NSInteger, CustomError) {
CustomErrorA = 0,
CustomErrorB = 1,
CustomErrorC = 2,
};
static NSString * const CustomErrorDomain = @"Project.CustomError";
In generated header:
Swift & Objective-C in the Same Project
Overriding Swift Names for Objective-C Interfaces
Class Factory Methods
+ (instancetype)recordWithRPM:(NSUInteger)RPM NS_SWIFT_NAME(init(rpm:));
+ (id)recordWithQuality:(double)quality NS_SWIFT_NAME(record(quality:));
typedef NS_ENUM(NSInteger, ABCRecordSide) {
ABCRecordSideA,
ABCRecordSideB NS_SWIFT_NAME(flipSide),
};
Enumerations
Swift compiler automatically imports Objective-C code as conventional Swift code.
Swift & Objective-C in the Same Project
Making Objective-C Interfaces Unavailable in Swift
Convenience Initializer
+ (instancetype)collectionWithValues:(NSArray *)values forKeys:
(NSArray<NSCopying> *)keys NS_SWIFT_UNAVAILABLE("Use a dictionary literal
instead");
Some Objective-C interfaces may not be suitable or necessary to be exposed as Swift
Objective-C class providing a convenience initializer that takes variadic arguments for keys-value
pairs may advise a Swift consumer to use a dictionary literal instead:
Swift & Objective-C in the Same Project
Refining Objective-C Declarations
use the NS_REFINED_FOR_SWIFT macro on an Objective-C method declaration to
provide a refined Swift interface in an extension
@interface Color : NSObject
- (void)getRed:(nullable CGFloat *)red
green:(nullable CGFloat *)green
blue:(nullable CGFloat *)blue
alpha:(nullable CGFloat *)alpha NS_REFINED_FOR_SWIFT;
@end
extension Color {
var RGBA: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var r: CGFloat = 0.0
var g: CGFloat = 0.0
var b: CGFloat = 0.0
var a: CGFloat = 0.0
__getRed(red: &r, green: &g, blue: &b, alpha: &a)
return (red: r, green: g, blue: b, alpha: a)
}
}
Swift & Objective-C in the Same Project
Troubleshooting Tips and Reminders

More Related Content

What's hot

ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
Ramesh Nair
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6
Nilesh Jayanandana
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
Nelson Glauber Leal
 
From android/java to swift (3)
From android/java to swift (3)From android/java to swift (3)
From android/java to swift (3)
allanh0526
 
Objective-Cひとめぐり
Objective-CひとめぐりObjective-Cひとめぐり
Objective-Cひとめぐり
Kenji Kinukawa
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java Developers
Bob McCune
 
Swift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-CSwift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-C
Alexis Gallagher
 
JavaScript Web Development
JavaScript Web DevelopmentJavaScript Web Development
JavaScript Web Development
vito jeng
 
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
Wanbok Choi
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptIngvar Stepanyan
 
Objective-C Crash Course for Web Developers
Objective-C Crash Course for Web DevelopersObjective-C Crash Course for Web Developers
Objective-C Crash Course for Web Developers
Joris Verbogt
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
Garth Gilmour
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java Developers
Michael Galpin
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
Cory Forsyth
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
Manoj Kumar
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
Nelson Glauber Leal
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
Bruno Scopelliti
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programmingjeffz
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat
 

What's hot (20)

ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6Introduction to Ecmascript - ES6
Introduction to Ecmascript - ES6
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
From android/java to swift (3)
From android/java to swift (3)From android/java to swift (3)
From android/java to swift (3)
 
Objective-Cひとめぐり
Objective-CひとめぐりObjective-Cひとめぐり
Objective-Cひとめぐり
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java Developers
 
Swift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-CSwift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-C
 
JavaScript Web Development
JavaScript Web DevelopmentJavaScript Web Development
JavaScript Web Development
 
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
 
Objective-C Crash Course for Web Developers
Objective-C Crash Course for Web DevelopersObjective-C Crash Course for Web Developers
Objective-C Crash Course for Web Developers
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java Developers
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programming
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 

Similar to Swift와 Objective-C를 함께 쓰는 방법

Working with Cocoa and Objective-C
Working with Cocoa and Objective-CWorking with Cocoa and Objective-C
Working with Cocoa and Objective-C
Kazunobu Tasaka
 
Real World Generics In Swift
Real World Generics In SwiftReal World Generics In Swift
Real World Generics In Swift
Vadym Markov
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
Ostap Andrusiv
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
Giordano Scalzo
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
Arawn Park
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - Oliviero
Codemotion
 
Play á la Rails
Play á la RailsPlay á la Rails
Play á la Rails
Sebastian Nozzi
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, SwiftYandex
 
TypeScript Best Practices
TypeScript Best PracticesTypeScript Best Practices
TypeScript Best Practices
felixbillon
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
HamletDRC
 
Cocoa for Web Developers
Cocoa for Web DevelopersCocoa for Web Developers
Cocoa for Web Developers
georgebrock
 
EclipseCon2011 Cross-Platform Mobile Development with Eclipse
EclipseCon2011 Cross-Platform Mobile Development with EclipseEclipseCon2011 Cross-Platform Mobile Development with Eclipse
EclipseCon2011 Cross-Platform Mobile Development with EclipseHeiko Behrens
 
360|iDev
360|iDev360|iDev
360|iDev
Aijaz Ansari
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
Istanbul Tech Talks
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 

Similar to Swift와 Objective-C를 함께 쓰는 방법 (20)

Working with Cocoa and Objective-C
Working with Cocoa and Objective-CWorking with Cocoa and Objective-C
Working with Cocoa and Objective-C
 
Real World Generics In Swift
Real World Generics In SwiftReal World Generics In Swift
Real World Generics In Swift
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - Oliviero
 
Day 1
Day 1Day 1
Day 1
 
Play á la Rails
Play á la RailsPlay á la Rails
Play á la Rails
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, Swift
 
Runtime
RuntimeRuntime
Runtime
 
TypeScript Best Practices
TypeScript Best PracticesTypeScript Best Practices
TypeScript Best Practices
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
Cocoa for Web Developers
Cocoa for Web DevelopersCocoa for Web Developers
Cocoa for Web Developers
 
EclipseCon2011 Cross-Platform Mobile Development with Eclipse
EclipseCon2011 Cross-Platform Mobile Development with EclipseEclipseCon2011 Cross-Platform Mobile Development with Eclipse
EclipseCon2011 Cross-Platform Mobile Development with Eclipse
 
360|iDev
360|iDev360|iDev
360|iDev
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 

More from Jung Kim

Let'Swift 2019 키노트
Let'Swift 2019 키노트Let'Swift 2019 키노트
Let'Swift 2019 키노트
Jung Kim
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
Jung Kim
 
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Jung Kim
 
Letswift18 키노트
Letswift18 키노트Letswift18 키노트
Letswift18 키노트
Jung Kim
 
개발자를 위한 넓고 얕은 지식
개발자를 위한 넓고 얕은 지식개발자를 위한 넓고 얕은 지식
개발자를 위한 넓고 얕은 지식
Jung Kim
 
스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내
Jung Kim
 
Let'Swift 17 키노트
Let'Swift 17 키노트Let'Swift 17 키노트
Let'Swift 17 키노트
Jung Kim
 
마스터즈 오픈세미나 - 소프트웨어가좋아요
마스터즈 오픈세미나 - 소프트웨어가좋아요마스터즈 오픈세미나 - 소프트웨어가좋아요
마스터즈 오픈세미나 - 소프트웨어가좋아요
Jung Kim
 
소프트웨어로 미래를 준비하는 사람들
소프트웨어로 미래를 준비하는 사람들소프트웨어로 미래를 준비하는 사람들
소프트웨어로 미래를 준비하는 사람들
Jung Kim
 
Developerway-2016-camp
Developerway-2016-campDeveloperway-2016-camp
Developerway-2016-camp
Jung Kim
 
Swift internals
Swift internalsSwift internals
Swift internals
Jung Kim
 
Swift2 smalltalk osxdev
Swift2 smalltalk osxdevSwift2 smalltalk osxdev
Swift2 smalltalk osxdev
Jung Kim
 
모바일 트렌드와 iOS
모바일 트렌드와 iOS모바일 트렌드와 iOS
모바일 트렌드와 iOS
Jung Kim
 
개발자로 살아가는 길, 그리고 NEXT
개발자로 살아가는 길, 그리고 NEXT개발자로 살아가는 길, 그리고 NEXT
개발자로 살아가는 길, 그리고 NEXT
Jung Kim
 
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
Jung Kim
 

More from Jung Kim (15)

Let'Swift 2019 키노트
Let'Swift 2019 키노트Let'Swift 2019 키노트
Let'Swift 2019 키노트
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
 
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
 
Letswift18 키노트
Letswift18 키노트Letswift18 키노트
Letswift18 키노트
 
개발자를 위한 넓고 얕은 지식
개발자를 위한 넓고 얕은 지식개발자를 위한 넓고 얕은 지식
개발자를 위한 넓고 얕은 지식
 
스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내
 
Let'Swift 17 키노트
Let'Swift 17 키노트Let'Swift 17 키노트
Let'Swift 17 키노트
 
마스터즈 오픈세미나 - 소프트웨어가좋아요
마스터즈 오픈세미나 - 소프트웨어가좋아요마스터즈 오픈세미나 - 소프트웨어가좋아요
마스터즈 오픈세미나 - 소프트웨어가좋아요
 
소프트웨어로 미래를 준비하는 사람들
소프트웨어로 미래를 준비하는 사람들소프트웨어로 미래를 준비하는 사람들
소프트웨어로 미래를 준비하는 사람들
 
Developerway-2016-camp
Developerway-2016-campDeveloperway-2016-camp
Developerway-2016-camp
 
Swift internals
Swift internalsSwift internals
Swift internals
 
Swift2 smalltalk osxdev
Swift2 smalltalk osxdevSwift2 smalltalk osxdev
Swift2 smalltalk osxdev
 
모바일 트렌드와 iOS
모바일 트렌드와 iOS모바일 트렌드와 iOS
모바일 트렌드와 iOS
 
개발자로 살아가는 길, 그리고 NEXT
개발자로 살아가는 길, 그리고 NEXT개발자로 살아가는 길, 그리고 NEXT
개발자로 살아가는 길, 그리고 NEXT
 
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
차세대컴파일러, VM의미래: 애플 오픈소스 LLVM
 

Recently uploaded

一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
zwunae
 
Technical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prismsTechnical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prisms
heavyhaig
 
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
bakpo1
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
obonagu
 
An Approach to Detecting Writing Styles Based on Clustering Techniques
An Approach to Detecting Writing Styles Based on Clustering TechniquesAn Approach to Detecting Writing Styles Based on Clustering Techniques
An Approach to Detecting Writing Styles Based on Clustering Techniques
ambekarshweta25
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
Kamal Acharya
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Sreedhar Chowdam
 
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
dxobcob
 
Harnessing WebAssembly for Real-time Stateless Streaming Pipelines
Harnessing WebAssembly for Real-time Stateless Streaming PipelinesHarnessing WebAssembly for Real-time Stateless Streaming Pipelines
Harnessing WebAssembly for Real-time Stateless Streaming Pipelines
Christina Lin
 
Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
manasideore6
 
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressionsKuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
Victor Morales
 
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
thanhdowork
 
Fundamentals of Induction Motor Drives.pptx
Fundamentals of Induction Motor Drives.pptxFundamentals of Induction Motor Drives.pptx
Fundamentals of Induction Motor Drives.pptx
manasideore6
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
Kamal Acharya
 
6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)
ClaraZara1
 
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdfWater Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation & Control
 
Literature Review Basics and Understanding Reference Management.pptx
Literature Review Basics and Understanding Reference Management.pptxLiterature Review Basics and Understanding Reference Management.pptx
Literature Review Basics and Understanding Reference Management.pptx
Dr Ramhari Poudyal
 
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
AJAYKUMARPUND1
 
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdf
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdfTutorial for 16S rRNA Gene Analysis with QIIME2.pdf
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdf
aqil azizi
 
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
zwunae
 

Recently uploaded (20)

一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
一比一原版(IIT毕业证)伊利诺伊理工大学毕业证成绩单专业办理
 
Technical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prismsTechnical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prisms
 
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
一比一原版(SFU毕业证)西蒙菲莎大学毕业证成绩单如何办理
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
 
An Approach to Detecting Writing Styles Based on Clustering Techniques
An Approach to Detecting Writing Styles Based on Clustering TechniquesAn Approach to Detecting Writing Styles Based on Clustering Techniques
An Approach to Detecting Writing Styles Based on Clustering Techniques
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
 
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
一比一原版(Otago毕业证)奥塔哥大学毕业证成绩单如何办理
 
Harnessing WebAssembly for Real-time Stateless Streaming Pipelines
Harnessing WebAssembly for Real-time Stateless Streaming PipelinesHarnessing WebAssembly for Real-time Stateless Streaming Pipelines
Harnessing WebAssembly for Real-time Stateless Streaming Pipelines
 
Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
 
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressionsKuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
KuberTENes Birthday Bash Guadalajara - K8sGPT first impressions
 
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
 
Fundamentals of Induction Motor Drives.pptx
Fundamentals of Induction Motor Drives.pptxFundamentals of Induction Motor Drives.pptx
Fundamentals of Induction Motor Drives.pptx
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
 
6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)
 
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdfWater Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdf
 
Literature Review Basics and Understanding Reference Management.pptx
Literature Review Basics and Understanding Reference Management.pptxLiterature Review Basics and Understanding Reference Management.pptx
Literature Review Basics and Understanding Reference Management.pptx
 
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
 
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdf
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdfTutorial for 16S rRNA Gene Analysis with QIIME2.pdf
Tutorial for 16S rRNA Gene Analysis with QIIME2.pdf
 
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
一比一原版(UMich毕业证)密歇根大学|安娜堡分校毕业证成绩单专业办理
 

Swift와 Objective-C를 함께 쓰는 방법

  • 2. * “Using Swift with Cocoa and Objective-C” / .
  • 4. Interacting with Objective-C APIs - (instancetype)init; - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style; init() { /* ... */ } init(frame: CGRect, style: UITableViewStyle) { /* ... */ } UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; let myTableView: UITableView = UITableView(frame: .zero, style: .grouped) let myTextField = UITextField(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 40.0)) Initialization • Objective-C • Swift
  • 5. Interacting with Objective-C APIs UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0]; let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0) Convenience Initializers • Objective-C • Swift To be used with the same syntax as initializers.
  • 6. Interacting with Objective-C APIs if let image = UIImage(contentsOfFile: "MyImage.png") { // loaded the image successfully } else { // could not load the image } Failable Initialization • Objective-C • Swift Initializers directly return the object they initialize. To inform the caller when initialization has failed, an Objective-C initializer can return nil.
  • 7. Interacting with Objective-C APIs Nullability Properties • Swift • Objective-C @property (nullable) id nullableProperty; @property (nonnull) id nonNullProperty; @property id unannotatedProperty; NS_ASSUME_NONNULL_BEGIN - (id)returnsNonNullValue; - (void)takesNonNullParameter:(id)value; NS_ASSUME_NONNULL_END - (nullable id)returnsNullableValue; - (void)takesNullableParameter:(nullable id)value; - (id)returnsUnannotatedValue; - (void)takesUnannotatedParameter:(id)value; var nullableProperty: Any? var nonNullProperty: Any var unannotatedProperty: Any! func returnsNonNullValue() -> Any func takesNonNullParameter(value: Any) func returnsNullableValue() -> Any? func takesNullableParameter(value: Any?) func returnsUnannotatedValue() -> Any! func takesUnannotatedParameter(value: Any!)
  • 8. Interacting with Objective-C APIs Accessing Properties • readonly = computed property { get } • weak = weak (weak var) • assign, copy, strong, unsafe_unretained • Class = Type • Atomic • Accessor (getter= / setter=)
  • 9. Interacting with Objective-C APIs myTableView.insertSubview(mySubview, at: 2) Working with Methods • Objective-C • Swift [myTableView insertSubview:mySubview atIndex:2]; myTableView.layoutIfNeeded() Can call Objective-C methods from Swift using dot syntax.
  • 10. Interacting with Objective-C APIs var x: Any = "hello" as String x as? String // String with value "hello" x as? NSString // NSString with value "hello" x = "goodbye" as NSString x as? String // String with value "goodbye" x as? NSString // NSString with value "goodbye" id • Objective-C • Swift The Objective-C id type is imported by Swift as the Any type.
  • 11. Interacting with Objective-C APIs let userDefaults = UserDefaults.standard let lastRefreshDate = userDefaults.object(forKey: "LastRefreshDate") // lastRefreshDate is of type Any? if let date = lastRefreshDate as? Date { print("(date.timeIntervalSinceReferenceDate)") } Downcasting Any let myDate = lastRefreshDate as! Date let timeInterval = myDate.timeIntervalSinceReferenceDate let myDate = lastRefreshDate as! String // Error Forced downcast operator (as!) Forced downcast error Conditional type cast operator (as?)
  • 12. Interacting with Objective-C APIs var myObject: AnyObject = UITableViewCell() myObject = NSDate() let futureDate = myObject.addingTimeInterval(10) let timeSinceNow = myObject.timeIntervalSinceNow Dynamic Method Lookup & Optional chaining AnyObject type lookup @objc method dynamically myObject.character(at: 5) // crash, myObject doesn't respond to that method let myCount = myObject.count // myCount has Int? type and nil value let myChar = myObject.character?(at: 5) // myChar has unichar? type and nil value if let fifthCharacter = myObject.character?(at: 5) { print("Found (fifthCharacter) at index 5") } // conditional branch not executed
  • 13. Interacting with Objective-C APIs Bridging Optionals to Nonnullable Objects @implementation OptionalBridging + (void)logSomeValue:(nonnull id)valueFromSwift { if ([valueFromSwift isKindOfClass: [NSNull class]]) { os_log(OS_LOG_DEFAULT, "Received an NSNull value."); } else { os_log(OS_LOG_DEFAULT, "%s", [valueFromSwift UTF8String]); } } @end let someValue: String? = "Bridge me, please." let nilValue: String? = nil OptionalBridging.logSomeValue(someValue as Any) // String OptionalBridging.logSomeValue(nilValue as Any) // an NSNull value. Optional nil NSNull , Optional unwrapped value [T?] => NSArray<T>
  • 14. Interacting with Objective-C APIs Lightweight Generics @property NSArray<NSDate *> *dates; @property NSCache<NSObject *, id<NSDiscardableContent>> *cachedData; @property NSDictionary <NSString *, NSArray<NSLocale *>> *supportedLocales; var dates: [Date] var cachedData: NSCache<AnyObject, NSDiscardableContent> var supportedLocales: [String: [Locale]] • Objective-C • Swift
  • 15. Interacting with Objective-C APIs Generic Class @interface List<T: id<NSCopying>> : NSObject - (List<T> *)listByAppendingItemsInList:(List<T> *)otherList; @end @interface ListContainer : NSObject - (List<NSValue *> *)listOfValues; @end @interface ListContainer (ObjectList) - (List *)listOfObjects; @end • Objective-C • Swift class List<T: NSCopying> : NSObject { func listByAppendingItemsInList(otherList: List<T>) -> List<T> } class ListContainer : NSObject { func listOfValues() -> List<NSValue> } extension ListContainer { func listOfObjects() -> List<NSCopying> }
  • 16. Interacting with Objective-C APIs Extensions (of existing classes, structures…) extension UIBezierPath { convenience init(triangleSideLength: CGFloat, origin: CGPoint) { self.init() let squareRoot = CGFloat(sqrt(3.0)) let altitude = (squareRoot * triangleSideLength) / 2 move(to: origin) addLine(to: CGPoint(x: origin.x + triangleSideLength, y: origin.y)) addLine(to: CGPoint(x: origin.x + triangleSideLength / 2, y: origin.y + altitude)) close() } } • Swift
  • 17. Interacting with Objective-C APIs Closures & Blocks void (^completionBlock)(NSData *) = ^(NSData *data) { // ... } • Swift • Objective-C let completionBlock: (Data) -> Void = { data in // ... } __weak typeof(self) weakSelf = self; self.block = ^{ __strong typeof(self) strongSelf = weakSelf; [strongSelf doSomething]; }; self.closure = { [unowned self] in self.doSomething() }
  • 18. Interacting with Objective-C APIs Object Comparison • Swift • Objective-C equality : ( -isEqual: ) identity : equality (==) : (Equatable ) == Operator isEqual: isEqual: identity (===) : === Operator
  • 19. Interacting with Objective-C APIs Hashing • Swift • Objective-C @property NSDictionary *unqualifiedDictionary; @property NSDictionary<NSString *, NSDate *> *qualifiedDictionary; @property NSSet *unqualifiedSet; @property NSSet<NSString *> *qualifiedSet; var unqualifiedDictionary: [AnyHashable: Any] var qualifiedDictionary: [String: Date] var unqualifiedSet: Set<AnyHashable> var qualifiedSet: Set<String>
  • 20. Interacting with Objective-C APIs Excludes Swift-only • Generics • Tuples • Enumerations defined in Swift without Int raw value type • Structures defined in Swift • Top-level functions defined in Swift • Global variables defined in Swift • Typealiases defined in Swift • Swift-style variadics • Nested types • Curried functions
  • 21. Interacting with Objective-C APIs Swift Type Compatibility class Jukebox: NSObject { var library: Set<String> var nowPlaying: String? var isCurrentlyPlaying: Bool { return nowPlaying != nil } class var favoritesPlaylist: [String] { // return an array of song names } init(songs: String...) { self.library = Set<String>(songs) } func playSong(named name: String) throws { // play song or throw an error if unavailable } } @interface Jukebox : NSObject @property (nonatomic, strong, nonnull) NSSet<NSString *> *library; @property (nonatomic, copy, nullable) NSString *nowPlaying; @property (nonatomic, readonly, getter=isCurrentlyPlaying) BOOL currentlyPlaying; @property (nonatomic, class, readonly, nonnull) NSArray<NSString *> * favoritesPlaylist; - (nonnull instancetype)initWithSongs:(NSArray<NSString *> * __nonnull)songs OBJC_DESIGNATED_INITIALIZER; - (BOOL)playSong:(NSString * __nonnull)name error:(NSError * __nullable * __null_unspecified)error; @end
  • 22. Interacting with Objective-C APIs Configuring Swift Interfaces @objc(Color) enum Цвет: Int { @objc(Red) case Красный @objc(Black) case Черный } @objc(Squirrel) class Белка: NSObject { @objc(color) var цвет: Цвет = .Красный @objc(initWithName:) init (имя: String) { // ... } @objc(hideNuts:inTree:) func прячьОрехи(количество: Int, вДереве дерево: Дерево) { // ... } }
  • 23. Interacting with Objective-C APIs Selectors import UIKit class MyViewController: UIViewController { let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50)) override init?(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) let action = #selector(MyViewController.tappedButton) myButton.addTarget(self, action: action, forControlEvents: .touchUpInside) } func tappedButton(sender: UIButton?) { print("tapped button") } required init?(coder: NSCoder) { super.init(coder: coder) } }
  • 24. Interacting with Objective-C APIs Unsafe Invocation of Objective-C Methods let string: NSString = "Hello, Cocoa!" let selector = #selector(NSString.lowercased(with:)) let locale = Locale.current if let result = string.perform(selector, with: locale) { print(result.takeUnretainedValue()) } // Prints "hello, cocoa!" let array: NSArray = ["delta", "alpha", "zulu"] // Not a compile-time error because NSDictionary has this selector. let selector = #selector(NSDictionary.allKeysForObject) // Raises an exception because NSArray does not respond to this selector. array.perform(selector) Perform Selector Unsafe invocation
  • 25. Interacting with Objective-C APIs Keys & Key Paths class Person: NSObject { var name: String var friends: [Person] = [] var bestFriend: Person? = nil init(name: String) { self.name = name } } let gabrielle = Person(name: "Gabrielle") let jim = Person(name: "Jim") let yuanyuan = Person(name: "Yuanyuan") gabrielle.friends = [jim, yuanyuan] gabrielle.bestFriend = yuanyuan #keyPath(Person.name) // "name" gabrielle.value(forKey: #keyPath(Person.name)) // "Gabrielle" #keyPath(Person.bestFriend.name) // "bestFriend.name" gabrielle.value(forKeyPath: #keyPath(Person.bestFriend.name)) // "Yuanyuan" #keyPath(Person.friends.name) // "friends.name" gabrielle.value(forKeyPath: #keyPath(Person.friends.name)) // ["Yuanyuan", "Jim"]
  • 26. Objective-C Behavior Inheriting from Objective-C Classes @IBDesignable, @IBInpectable let myPersonClass: AnyClass? = NSClassFromString("MyGreatApp.Person")
  • 27. Working with Cocoa Frameworks Foundation
  • 28. Working with Cocoa Frameworks Core Foundation CFStringRef StringByAddingTwoStrings(CFStringRef s1, CFStringRef s2) func StringByAddingTwoStrings(_: CFString!, _: CFString!) -> Unmanaged<CFString>! { // ... } let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue() CFTypeRef remaps to the AnyObject CFStringRef remaps to the CFString class takeRetainedValue()
  • 29. Working with Cocoa Frameworks Unified Logging import os.log os_log("This is a log message.”) let fileSize = 1234567890 os_log("Finished downloading file. Size: %{iec-bytes}d", fileSize) os_log("This is additional info that may be helpful for troubleshooting.", type: .info) let customLog = OSLog("com.your_company.your_subsystem_name.plist", "your_category_name") os_log("This is info that may be helpful during development or debugging.", log: customLog, type: .debug)
  • 30. Working with Cocoa Frameworks Cocoa structure NSValue MKCoordinateSpan NSRange CLLocationCoordinate2D CATransform3D, CGAffineTransform CGPoint, CGRect, CGSize, CGVector CMTimeMapping, CMTimeRange, CMTime SCNMatrix4, SCNVector3, SCNVector4 UIEdgeInsets, UIOffset NSValue
  • 31. Adopting Cocoa Design Patterns Delegation 1)Check that myDelegate is not nil. 2)Check that myDelegate implements the method window:willUseFullScreenContentSize:. 3)If 1 and 2 hold true, invoke the method and assign the result of the method to the value named fullScreenSize. 4)Print the return value of the method. class MyDelegate: NSObject, NSWindowDelegate { func window(_ window: NSWindow, willUseFullScreenContentSize proposedSize: NSSize) -> NSSize { return proposedSize } } //… myWindow.delegate = MyDelegate() if let fullScreenSize = myWindow.delegate?.window(myWindow, willUseFullScreenContentSize: mySize) { print(NSStringFromSize(fullScreenSize)) }
  • 32. Adopting Cocoa Design Patterns Lazy Initialization @property NSXMLDocument *XML; - (NSXMLDocument *)XML { if (_XML == nil) { _XML = [[NSXMLDocument alloc] initWithContentsOfURL:[[Bundle mainBundle] URLForResource:@"/path/to/resource" withExtension:@"xml"] options:0 error:nil]; } return _XML; } lazy var XML: XMLDocument = try! XMLDocument(contentsOf: Bundle.main.url(forResource: "document", withExtension: "xml")!, options: 0) • Objective-C • Swift
  • 33. Adopting Cocoa Design Patterns Lazy property var pattern: String lazy var regex: NSRegularExpression = try! NSRegularExpression(pattern: self.pattern, options: []) lazy var currencyFormatter: NumberFormatter = { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencySymbol = "¤" return formatter }() • Swift use self-evaluating closure
  • 34. Adopting Cocoa Design Patterns Error Handling NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *fromURL = [NSURL fileURLWithPath:@"/path/to/old"]; NSURL *toURL = [NSURL fileURLWithPath:@"/path/to/new"]; NSError *error = nil; BOOL success = [fileManager moveItemAtURL:fromURL toURL:toURL error:&error]; if (!success) { NSLog(@"Error: %@", error.domain); } • Swift • Objective-C let fileManager = FileManager.default let fromURL = URL(fileURLWithPath: "/path/to/old") let toURL = URL(fileURLWithPath: "/path/to/new") do { try fileManager.moveItem(at: fromURL, to: toURL) } catch let error as NSError { print("Error: (error.domain)") }
  • 35. Adopting Cocoa Design Patterns Converting errors to Optional values • Swift • Objective-C NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *tmpURL = [fileManager URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil]; if (tmpURL != nil) { // ... } let fileManager = FileManager.default if let tmpURL = try? fileManager.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) { // ... }
  • 36. Adopting Cocoa Design Patterns Throwing error • Swift • Objective-C // an error occurred if (errorPtr) { *errorPtr = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotOpenFile userInfo:nil]; } // an error occurred throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)
  • 37. Adopting Cocoa Design Patterns Key-value Observing KVO with a Swift class inherits from NSObject class 1) Add dynamic modifier to any property 2) Create a global context variable 3) Add an observer for the key-path, override the observeValue() method and remove the observer in deinit. class MyObjectToObserve: NSObject { dynamic var myDate = NSDate() func updateDate() { myDate = NSDate() } } private var myContext = 0 class MyObserver: NSObject { var objectToObserve = MyObjectToObserve() override init() { super.init() objectToObserve.addObserver(self, forKeyPath: #keyPath(MyObjectToObserve.myDate), options: .new, context: &myContext) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if context == &myContext { if let newValue = change?[.newKey] { print("Date changed: (newValue)”) } } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) } } deinit { objectToObserve.removeObserver(self, forKeyPath: #keyPath(MyObjectToObserve.myDate), context: &myContext) } }
  • 38. Adopting Cocoa Design Patterns Undo architecture Create an undo operation using an NSInvocation @IBOutlet var remainingLabel: NSTextView! func mark(task: Task, asCompleted completed: Bool) { if let target = undoManager?.prepare(withInvocationTarget: self) as? ToDoListController { target.mark(task: task, asCompleted: !completed) undoManager?.setActionName(NSLocalizedString("todo.task.mark", comment: "Mark As Completed")) } task.completed = completed tableView.reloadData() let numberRemaining = tasks.filter{ $0.completed }.count remainingLabel.string = String(format: NSLocalizedString("todo.task.remaining", comment: "Tasks Remaining: %d"), numberRemaining) }
  • 39. Adopting Cocoa Design Patterns Singleton initialization in a call the dispatch_once function + (instancetype)sharedInstance { static id _sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[self alloc] init]; }); return _sharedInstance; } class Singleton { static let sharedInstance = Singleton() } class Singleton { static let sharedInstance: Singleton = { let instance = Singleton() // setup code return instance }() }
  • 40. Adopting Cocoa Design Patterns Introspection use the isKindOfClass: method or conformsToProtocol: method if object is UIButton { // object is of type UIButton } else { // object is not of type UIButton } if let button = object as? UIButton { // object is successfully cast to type UIButton and bound to button } else { // object could not be cast to type UIButton } if let dataSource = object as? UITableViewDataSource { // object conforms to UITableViewDataSource and is bound to dataSource } else { // object not conform to UITableViewDataSource } • Swift • Objective-C
  • 41. Adopting Cocoa Design Patterns Serialization To encode and decode objects to and from architecture-independent representations. Use NSJSONSerialization and NSPropertyListSerialization import Foundation import CoreLocation struct Venue { enum Category: String { case entertainment case food case nightlife case shopping } var name: String var coordinates: CLLocationCoordinate2D var category: Category } { "name": "Caffè Macs", "coordinates": { "lat": 37.330576, "lng": -122.029739 }, "category": "food" }
  • 42. Adopting Cocoa Design Patterns Serialization : Initializer init?(attributes: [String: Any]) { guard let name = attributes["name"] as? String, let coordinates = attributes["coordinates"] as? [String: Double], let latitude = coordinates["lat"], let longitude = coordinates["lng"], let category = Category(rawValue: attributes["category"] as? String ?? "Invalid") else { return nil } self.name = name self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) self.category = category } let JSON = "{"name": "Caffè Macs","coordinates": {"lat": 37.330576,"lng": -122.029739}, "category": "food"}" let data = JSON.data(using: String.Encoding.utf8)! let attributes = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] let venue = Venue(attributes: attributes)! print(venue.name) // Prints "Caffè Macs" Initialize with Dictionary<String, Any> Create a Venue from a JSON representation
  • 43. Adopting Cocoa Design Patterns Serialization : Validating enum ValidationError: Error { case missing(String) case invalid(String) } init(attributes: [String: Any]) throws { guard let name = attributes["name"] as? String else { throw ValidationError.missing("name") } guard let coordinates = attributes["coordinates"] as? [String: Double] else { throw ValidationError.missing("coordinates") } guard let latitude = coordinates["lat"], let longitude = coordinates["lng"] else { throw ValidationError.invalid("coordinates") } guard let categoryName = attributes["category"] as? String else { throw ValidationError.missing("category") } guard let category = Category(rawValue: categoryName) else { throw ValidationError.invalid("category") } self.name = name self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) self.category = category }
  • 44. Adopting Cocoa Design Patterns Localization use NSLocalizedString, NSLocalizedStringFromTable, NSLocalizedStringFromTableInBundle, NSLocalizedStringWithDefaultValue • Objective-C • Swift A single function: NSLocalizedString(_:tableName:bundle:value:comment:) let format = NSLocalizedString("Hello, %@!", comment: "Hello, {given name}!") let name = "Mei" let greeting = String(format: format, arguments: [name as CVarArg]) print(greeting) // Prints "Hello, Mei!" if let path = Bundle.main.path(forResource: "Localization", ofType: "strings", inDirectory: nil, forLocalization: "ja"), let bundle = Bundle(path: path) { let translation = NSLocalizedString("Hello", bundle: bundle, comment: "") print(translation) } // Prints " "
  • 45. Adopting Cocoa Design Patterns API Availability use respondsToSelector: and instancesRespondToSelector: methods • Objective-C • Swift let locationManager = CLLocationManager() if #available(iOS 8.0, macOS 10.10, *) { locationManager.requestWhenInUseAuthorization() } if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) { // Method is available for use. } else { // Method is not available. } let locationManager = CLLocationManager() guard #available(iOS 8.0, macOS 10.10, *) else { return } locationManager.requestWhenInUseAuthorization()
  • 46. Adopting Cocoa Design Patterns Processing Command-Line Arguments for argument in CommandLine.arguments { print(argument) } // prints "/path/to/app" // prints "--argumentName" // prints "value" $ /path/to/app --argumentName value
  • 47. Interacting with C APIs Primitive Types C Type Swift Type bool CBool char, signed char CChar unsigned char CUnsignedChar short CShort unsigned short CUnsignedShort int CInt unsigned int CUnsignedInt long CLong unsigned long CUnsignedLong long long CLongLong unsigned long long CUnsignedLongLong wchar_t CWideChar char16_t CChar16 char32_t CChar32 float CFloat double CDouble
  • 48. Interacting with C APIs Importing Constant Enumerations and Structures Annotate an typedef declaration with the NS_STRING_ENUM or NS_EXTENSIBLE_STRING_ENUM • Objective-C • Swift struct TrafficLightColor: RawRepresentable { typealias RawValue = String init(rawValue: RawValue) var rawValue: RawValue { get } static var red: TrafficLightColor { get } static var yellow: TrafficLightColor { get } static var green: TrafficLightColor { get } } typedef NSString * TrafficLightColor NS_STRING_ENUM; TrafficLightColor const TrafficLightColorRed; TrafficLightColor const TrafficLightColorYellow; TrafficLightColor const TrafficLightColorGreen;
  • 49. Interacting with C APIs Functions Any function declared in a C header as a Swift global function. • Objective-C • Swift func product(_ multiplier: Int32, _ multiplicand: Int32) -> Int32 func quotient(_ dividend: Int32, _ divisor: Int32, _ remainder: UnsafeMutablePointer<Int32>) -> Int32 func createPoint2D(_ x: Float, _ y: Float) -> Point2D func distance(_ from: Point2D, _ to: Point2D) -> Float int product(int multiplier, int multiplicand); int quotient(int dividend, int divisor, int *remainder); struct Point2D createPoint2D(float x, float y); float distance(struct Point2D from, struct Point2D to);
  • 50. Interacting with C APIs Variadic Functions Call C variadic functions, such as vasprintf, using the getVaList() or withVaList() func swiftprintf(format: String, arguments: CVarArg...) -> String? { return withVaList(arguments) { va_list in var buffer: UnsafeMutablePointer<Int8>? = nil return format.withCString { CString in guard vasprintf(&buffer, CString, va_list) != 0 else { return nil } return String(validatingUTF8: buffer!) } } } print(swiftprintf(format: "√2 ≅ %g", arguments: sqrt(2.0))!) // Prints "√2 ≅ 1.41421"
  • 51. Interacting with C APIs Structures Any C Structure declared in a C header as a Swift structure. struct Color { float r, g, b; }; typedef struct Color Color; public struct Color { var r: Float var g: Float var b: Float init() init(r: Float, g: Float, b: Float) } • Swift
  • 52. Interacting with C APIs Importing Functions as Type Members Use CF_SWIFT_NAME macro in you own code Color ColorCreateWithCMYK(float c, float m, float y, float k) CF_SWIFT_NAME(Color.init(c:m:y:k:)); float ColorGetHue(Color color) CF_SWIFT_NAME(getter:Color.hue(self:)); void ColorSetHue(Color color, float hue) CF_SWIFT_NAME(setter:Color.hue(self:newValue:)); Color ColorDarkenColor(Color color, float amount) CF_SWIFT_NAME(Color.darken(self:amount:)); extern const Color ColorBondiBlue CF_SWIFT_NAME(Color.bondiBlue); Color ColorGetCalibrationColor(void) CF_SWIFT_NAME(getter:Color.calibration()); Color ColorSetCalibrationColor(Color color) CF_SWIFT_NAME(setter:Color.calibration(newValue:)); extension Color { init(c: Float, m: Float, y: Float, k: Float) var hue: Float { get set } func darken(amount: Float) -> Color static var bondiBlue: Color static var calibration: Color } • Swift
  • 53. Interacting with C APIs Enumerations Any C enumeration marked with the NS_ENUM macro as a Swift Enumeration(Int) typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle }; enum UITableViewCellStyle: Int { case `default` case value1 case value2 case subtitle } • Swift let cellStyle: UITableViewCellStyle = .default
  • 54. Interacting with C APIs Enumerations : Option Sets Any C enumeration marked with the NS_OPTIONS macro as a Swift option set. typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, UIViewAutoresizingFlexibleRightMargin = 1 << 2, UIViewAutoresizingFlexibleTopMargin = 1 << 3, UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; public struct UIViewAutoresizing : OptionSet { public init(rawValue: UInt) public static var flexibleLeftMargin: UIViewAutoresizing { get } public static var flexibleWidth: UIViewAutoresizing { get } public static var flexibleRightMargin: UIViewAutoresizing { get } public static var flexibleTopMargin: UIViewAutoresizing { get } public static var flexibleHeight: UIViewAutoresizing { get } public static var flexibleBottomMargin: UIViewAutoresizing { get } } • Swift
  • 55. Interacting with C APIs Unions Swift imports C unions as Swift structures, not support unions. union SchroedingersCat { bool isAlive; bool isDead; }; struct SchroedingersCat { var isAlive: Bool { get set } var isDead: Bool { get set } init(isAlive: Bool) init(isDead: Bool) init() } • Swift
  • 56. Interacting with C APIs Unnamed Structure and Union Fields C struct and union types can define fields that have no name or that are of an unnamed type. struct Cake { union { int layers; double height; }; struct { bool icing; bool sprinkles; } toppings; }; var simpleCake = Cake() simpleCake.layers = 5 print(simpleCake.toppings.icing) // Prints "false" let cake = Cake( .init(layers: 2), toppings: .init(icing: true, sprinkles: false) ) print("The cake has (cake.layers) layers.") // Prints "The cake has 2 layers." print("Does it have sprinkles?", cake.toppings.sprinkles ? "Yes." : "No.") // Prints "Does it have sprinkles? No."
  • 57. Interacting with C APIs Pointers C Syntax Swift Syntax const Type * UnsafePointer<Type> Type * UnsafeMutablePointer<Type> C Syntax Swift Syntax Type * const * UnsafePointer<Type> Type * __strong * UnsafeMutablePointer<Type> Type ** AutoreleasingUnsafeMutablePointer<Type> C Syntax Swift Syntax const void * UnsafePointer void * UnsafeMutablePointer For return types, variables, and arguments For class types For pointers to untyped, raw memory
  • 58. Interacting with C APIs Constant Pointers func takesAPointer(_ p: UnsafePointer<Float>) { // ... } var x: Float = 0.0 takesAPointer(&x) takesAPointer([1.0, 2.0, 3.0]) var x: Float = 0.0, y: Int = 0 takesARawPointer(&x) takesARawPointer(&y) takesARawPointer([1.0, 2.0, 3.0] as [Float]) let intArray = [1, 2, 3] takesARawPointer(intArray) func takesARawPointer(_ p: UnsafeRawPointer?) { // ... }
  • 59. Interacting with C APIs Mutable Pointers func takesAMutablePointer(_ p: UnsafeMutablePointer<Float>) { // ... } var x: Float = 0.0 var a: [Float] = [1.0, 2.0, 3.0] takesAMutablePointer(&x) takesAMutablePointer(&a) var x: Float = 0.0, y: Int = 0 var a: [Float] = [1.0, 2.0, 3.0], b: [Int] = [1, 2, 3] takesAMutableRawPointer(&x) takesAMutableRawPointer(&y) takesAMutableRawPointer(&a) takesAMutableRawPointer(&b) func takesAMutableRawPointer(_ p: UnsafeMutableRawPointer?) { // ... }
  • 60. Interacting with C APIs Autoreleasing Pointers func takesAnAutoreleasingPointer(_ p: AutoreleasingUnsafeMutablePointer<NSDate?>) { // ... } var x: NSDate? = nil takesAnAutoreleasingPointer(&x)
  • 61. Interacting with C APIs Function Pointers func customCopyDescription(_ p: UnsafeRawPointer?) -> Unmanaged<CFString>? { // return an Unmanaged<CFString>? value } var callbacks = CFArrayCallBacks( version: 0, retain: nil, release: nil, copyDescription: customCopyDescription, equal: { (p1, p2) -> DarwinBoolean in // return Bool value } ) var mutableArray = CFArrayCreateMutable(nil, 0, &callbacks) C function pointers are imported into Swift as closures with C function pointer calling convention, denoted by the @convention(c) attribute.
  • 62. Interacting with C APIs Buffer Pointers & Null Pointers Buffer Pointers : Used for low-level access to a region of memory. UnsafeBufferPointer UnsafeMutableBufferPointer UnsafeRawBufferPointer UnsafeMutableRawBufferPointer Objective-C Syntax Swift Syntax const Type * _Nonnull UnsafePointer<Type> const Type * _Nullable UnsafePointer<Type>? const Type * _Null_unspecified UnsafePointer<Type>! Null Pointers Pointers Arithmatic let pointer: UnsafePointer<Int8> let offsetPointer = pointer + 24 // offsetPointer is 24 strides ahead of pointer
  • 63. Interacting with C APIs Data Type Size Calculation In C, the sizeof and alignof operators return the size and alignment In Swift, you use MemoryLayout<T> to access the memory layout of the parameterized type T through the size, stride, and alignment properties. print(MemoryLayout<timeval>.size) // Prints "16" print(MemoryLayout<timeval>.stride) // Prints "16" print(MemoryLayout<timeval>.alignment) // Prints "8" let sockfd = socket(AF_INET, SOCK_STREAM, 0) var optval = timeval(tv_sec: 30, tv_usec: 0) let optlen = socklen_t(MemoryLayout<timeval>.size) if setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &optval, optlen) == 0 { // ... }
  • 64. Interacting with C APIs Preprocessor Directives Simple Macro Complex Macro, no counterpart in Swift Conditional Compilation Blocks #if DEBUG_LOGGING print("Flag enabled.") #endif #define FADE_ANIMATION_DURATION 0.35 let FADE_ANIMATION_DURATION = 0.35 Function Valid arguments os() macOS, iOS, watchOS, tvOS, Linux arch() x86_64, arm, arm64, i386 swift() >= followed by a version number #if arch(arm) || arch(arm64) #if swift(>=3.0) print("Using Swift 3 ARM code") #else print("Using Swift 2.2 ARM code") #endif #elseif arch(x86_64) print("Using 64-bit x86 code.") #else print("Using general code.") #endif
  • 66. Mix and Match Overview
  • 67. Swift & Objective-C in the Same Project Importing Objective-C into Swift rely on an Objective-C bridging header to expose those files to Swift {product module name} + "-Bridging-Header.h" ex. = CodesquadApp CodesquadApp-Bridging-Header.h To import Objective-C code into Swift from the same target 1) In your Objective-C bridging header file, import every Objective-C header 2) In Build Settings > Swift Compiler - Code Generation, make sure the Objective-C Bridging Header build setting has a path to the bridging header file
  • 68. Swift & Objective-C in the Same Project Importing Swift into Objective-C rely on an Xcode-generated header file to expose those files to Objective-C {product module name} + "-Swift.h" ex. = CodesquadApp CodesquadApp-Swift.h The generated header contains interfaces for Swift declarations marked with the public or open modifier. An umbrella header for your Swift code Marked with the internal modifier if your app target has bridging header. To import Swift code into Objective-C from the same target #import "ProductModuleName-Swift.h"
  • 69. Swift & Objective-C in the Same Project Importing External Frameworks Swift code import FrameworkName @import FrameworkName; Objective-C code Import into Swift Import into Objective-C Any language framework import FrameworkName @import FrameworkName;
  • 70. Swift & Objective-C in the Same Project Using Swift from Objective-C Swift class MySwiftClass *swiftObject = [[MySwiftClass alloc] init]; [swiftObject swiftMethod]; // MyObjcClass.h @class MySwiftClass; @protocol MySwiftProtocol; @interface MyObjcClass : NSObject - (MySwiftClass *)returnSwiftClassInstance; - (id <MySwiftProtocol>)returnInstanceAdoptingSwiftProtocol; // ... @end Referencing a Swift Class or Protocol in an Objective-C Header
  • 71. Swift & Objective-C in the Same Project Using Swift from Objective-C Declaring a Swift Protocol That Can Be Adopted by an Objective-C Class @objc public protocol MySwiftProtocol { func requiredMethod() @objc optional func optionalMethod() } // MyObjcClass.m #import "ProductModuleName-Swift.h" @interface MyObjcClass () <MySwiftProtocol> // ... @end @implementation MyObjcClass // ... @end Adopting a Swift Protocol in an Objective-C Implementation
  • 72. Swift & Objective-C in the Same Project Using Swift from Objective-C Declaring a Swift Error Type That Can Be Used from Objective-C @objc public enum CustomError: Int, Error { case a, b, c } // Project-Swift.h typedef SWIFT_ENUM(NSInteger, CustomError) { CustomErrorA = 0, CustomErrorB = 1, CustomErrorC = 2, }; static NSString * const CustomErrorDomain = @"Project.CustomError"; In generated header:
  • 73. Swift & Objective-C in the Same Project Overriding Swift Names for Objective-C Interfaces Class Factory Methods + (instancetype)recordWithRPM:(NSUInteger)RPM NS_SWIFT_NAME(init(rpm:)); + (id)recordWithQuality:(double)quality NS_SWIFT_NAME(record(quality:)); typedef NS_ENUM(NSInteger, ABCRecordSide) { ABCRecordSideA, ABCRecordSideB NS_SWIFT_NAME(flipSide), }; Enumerations Swift compiler automatically imports Objective-C code as conventional Swift code.
  • 74. Swift & Objective-C in the Same Project Making Objective-C Interfaces Unavailable in Swift Convenience Initializer + (instancetype)collectionWithValues:(NSArray *)values forKeys: (NSArray<NSCopying> *)keys NS_SWIFT_UNAVAILABLE("Use a dictionary literal instead"); Some Objective-C interfaces may not be suitable or necessary to be exposed as Swift Objective-C class providing a convenience initializer that takes variadic arguments for keys-value pairs may advise a Swift consumer to use a dictionary literal instead:
  • 75. Swift & Objective-C in the Same Project Refining Objective-C Declarations use the NS_REFINED_FOR_SWIFT macro on an Objective-C method declaration to provide a refined Swift interface in an extension @interface Color : NSObject - (void)getRed:(nullable CGFloat *)red green:(nullable CGFloat *)green blue:(nullable CGFloat *)blue alpha:(nullable CGFloat *)alpha NS_REFINED_FOR_SWIFT; @end extension Color { var RGBA: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { var r: CGFloat = 0.0 var g: CGFloat = 0.0 var b: CGFloat = 0.0 var a: CGFloat = 0.0 __getRed(red: &r, green: &g, blue: &b, alpha: &a) return (red: r, green: g, blue: b, alpha: a) } }
  • 76. Swift & Objective-C in the Same Project Troubleshooting Tips and Reminders