Skip to content

Commit ec1e76a

Browse files
committed
Merge pull request #26 from rakaramos/source
Add "Easy cast with _ObjectiveCBridgeable" hint
2 parents 7442a91 + 633b6e1 commit ec1e76a

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
layout: post
3+
title: "Easy cast with _ObjectiveCBridgeable"
4+
date: 2015-10-07 19:15:43 +0200
5+
comments: true
6+
author: rafa
7+
categories:
8+
---
9+
10+
Swift is out there for about a year and it's a great programming language. I think that almost every iOS/OSX developer out there has already written couple of things in Swift (if you haven't, go ahead and try, you won't regret it, I promise). Although, we have many years of libs and frameworks built using Objective-C and sooner or later a project may have both Swift and Objective-C working together.
11+
12+
Fortunately, Apple gave us a [book](https://itunes.apple.com/us/book/using-swift-cocoa-objective/id888894773?mt=11) and a couple of WWDC session ([here](https://developer.apple.com/videos/play/wwdc2014-406/) and [here](https://developer.apple.com/videos/play/wwdc2015-401/)) with the intent to help developers on this task.
13+
14+
For those who have some experience with this integration knows that casting plays an important role. So, todays hint will dig into an poor documented protocol called `_ObjectiveCBridgeable`.
15+
16+
The documentation, which is only founded in header files says:
17+
18+
> A Swift Array or Dictionary of types conforming to _ObjectiveCBridgeable can be passed to Objective-C as an NSArray or NSDictionary, respectively. The elements of the resulting NSArray or NSDictionary will be the result of calling _bridgeToObjectiveC on each element of the source container.
19+
20+
Ok, but there is something else you can do with that, which is very handy.
21+
22+
Suppose that you have this class in Objective-C:
23+
24+
```objc
25+
@interface OPerson: NSObject
26+
27+
- (instancetype)initWithName:(NSString *)name surname:(NSString *)surname;
28+
29+
@property (nonatomic, copy) (NSString *)name;
30+
@property (nonatomic, copy) (NSString *)surname;
31+
32+
@end
33+
```
34+
35+
Now you want to easily cast this class into a Swift struct. Yes, we can! All you have to do is conform to `_ObjectiveCBridgeable`, like so:
36+
37+
```swift
38+
struct Person {
39+
let name: String
40+
let surname: String
41+
}
42+
43+
extension Person: _ObjectiveCBridgeable {
44+
45+
typealias _ObjectiveCType = OPerson
46+
47+
static func _isBridgedToObjectiveC() -> Bool {
48+
return type
49+
}
50+
51+
static func _getObjectiveCType() -> Any.Type {
52+
return ObjectiveCType.self
53+
}
54+
55+
func _bridgeToObjectiveC() -> _ObjectiveCType {
56+
return OPerson(name: name, surname: surname)
57+
}
58+
59+
static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Person?) {
60+
result = Person(name: source.name, surname: source.name)
61+
}
62+
63+
static func _conditionallyBridgeFRomObjectiveC(source: _ObjectiveCType, inout result: Person?) -> Bool {
64+
_forceBridgeFromObjectiveC(source, result: &result)
65+
return true
66+
}
67+
}
68+
```
69+
70+
And voilá!
71+
72+
```swift
73+
74+
let objcPerson = OPerson(name: "John", surname: "Doe")
75+
76+
if let swiftPerson = objcPerson as? Person {
77+
//will work
78+
}
79+
80+
let swiftPerson = objcPerson as Person //this too!
81+
82+
let swiftPerson2 = Person(name: "Jack", surname:"Doe")
83+
let objcPerson = swiftPerson2 as OPerson //and that
84+
85+
let person: OPerson = Person(name: "Alfred", surname: "Doe") //hooray
86+
```
87+
88+
Oh, that's so beautiful, don't you think? :]

0 commit comments

Comments
 (0)