SlideShare a Scribd company logo
1 of 34
Download to read offline
How to build a debug view
(almost) for free
Vincent Pradeilles (@v_pradeilles) & Benoît Caron – Worldline !
Why?
Why?
You have to make sure an app displays properly on the iPhone X, but:
• Data is driven by web-services
• No mocks are available
• More than 150 different screens
• Some screens are part of complex business scenarios
What would be the right tool?
A debug view!
• Lists all available UIViewControllers
• Indicate a specific use case, if
needed
• Instantiates, then pushes or
presents the controller
How do we get the data?
Objective-C
import ObjectiveC
The ObjectiveC module
• Exposes C APIs to interact with the ObjectiveC runtime
• Perfectly OK to use it with Swift
The ObjectiveC module
func objc_copyClassNamesForImage(_ image: UnsafePointer<Int8>,
_ outCount: UnsafeMutablePointer<UInt32>?)
-> UnsafeMutablePointer<UnsafePointer<Int8>>?
• This function returns a list of all the classes defined in a given bundle
• That’s all the data you’ll ever need to build a basic debug view!
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
extension Bundle {
func retrieveAllViewControllers() -> [String] {
guard let bundlePath = self.executablePath else { return [] }
var viewControllers = [String]()
var size: UInt32 = 0
let classes = objc_copyClassNamesForImage(bundlePath, &size)
for index in 0..<size {
if let className = classes?[Int(index)],
let name = NSString.init(utf8String:className) as String?,
NSClassFromString(name) is UIViewController.Type
{
viewControllers.append(name)
}
}
return viewControllers
}
}
How to use it?
func instantiateController(named name: String) -> UIViewController? {
let controllerClass = NSClassFromString(name) as? UIViewController.Type
return controllerClass?.init()
}
That’s it!
🎉
We’ve just seen the « free » part…
…let’s look at the « almost » side of things
Providing Initial Data
@objc public protocol DebugViewCompliant {
func prepareForDebugView()
}
extension MyViewController: DebugViewCompliant {
func prepareForDebugView() {
// do some configuration
}
}
Handling Use Cases
@objc public protocol DebugViewUseCaseCompliant {
static func getUseCases() -> [String]
func prepareForDebugView(useCase: String)
}
extension MyViewController: DebugViewUseCaseCompliant {
static func getUseCases() -> [String] {
return ["User Not Logged", "User Logged In"]
}
func prepareForDebugView(useCase: String) {
// do some configuration according to `useCase`
}
}
Working with Storyboards
@objc public protocol DebugViewInstantiable {
static func initForDebugView() -> UIViewController
}
extension MyViewController: DebugViewInstantiable {
static func initForDebugView() -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController =
storyboard.instantiateViewController("MyViewController") as!
MyViewController
return viewController
}
}
Does it work on a real project?
Does it work on a real project?
YES!
How can I use it?
How can I use it?
• Available on Github : https://github.com/worldline/ControllerFactory
• Works with CocoaPods and Carthage
• You just need to call:
ControllerFactory.instantiate(bundle: Bundle.main)
• Only one limitation: it does not work with generic classes 😕
😊
See you tomorrow!

More Related Content

What's hot

Basic data structures in python
Basic data structures in pythonBasic data structures in python
Basic data structures in pythonLifna C.S
 
Java Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream APIJava Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream APISvetlin Nakov
 
Profiling ruby
Profiling rubyProfiling ruby
Profiling rubynasirj
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsGlobalLogic Ukraine
 
The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189Mahmoud Samir Fayed
 
Java Foundations: Lists, ArrayList<T>
Java Foundations: Lists, ArrayList<T>Java Foundations: Lists, ArrayList<T>
Java Foundations: Lists, ArrayList<T>Svetlin Nakov
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84Mahmoud Samir Fayed
 
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...Databricks
 
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...Matthew Tovbin
 
The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 57 of 212
The Ring programming language version 1.10 book - Part 57 of 212The Ring programming language version 1.10 book - Part 57 of 212
The Ring programming language version 1.10 book - Part 57 of 212Mahmoud Samir Fayed
 

What's hot (17)

Basic data structures in python
Basic data structures in pythonBasic data structures in python
Basic data structures in python
 
Java Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream APIJava Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream API
 
Profiling ruby
Profiling rubyProfiling ruby
Profiling ruby
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
 
The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189
 
Java Foundations: Lists, ArrayList<T>
Java Foundations: Lists, ArrayList<T>Java Foundations: Lists, ArrayList<T>
Java Foundations: Lists, ArrayList<T>
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84
 
JDBC Core Concept
JDBC Core ConceptJDBC Core Concept
JDBC Core Concept
 
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
 
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
 
Managing Mocks
Managing MocksManaging Mocks
Managing Mocks
 
The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31
 
Module06
Module06Module06
Module06
 
The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212
 
The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196
 
The Ring programming language version 1.10 book - Part 57 of 212
The Ring programming language version 1.10 book - Part 57 of 212The Ring programming language version 1.10 book - Part 57 of 212
The Ring programming language version 1.10 book - Part 57 of 212
 

Similar to How to build a debug view almost for free

How to instantiate any view controller for free
How to instantiate any view controller for freeHow to instantiate any view controller for free
How to instantiate any view controller for freeBenotCaron
 
Optimize CollectionView Scrolling
Optimize CollectionView ScrollingOptimize CollectionView Scrolling
Optimize CollectionView ScrollingAndrea Prearo
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSTechWell
 
Swift Tableview iOS App Development
Swift Tableview iOS App DevelopmentSwift Tableview iOS App Development
Swift Tableview iOS App DevelopmentKetan Raval
 
Tutorial mvc (pelajari ini jika ingin tahu mvc) keren
Tutorial mvc (pelajari ini jika ingin tahu mvc) kerenTutorial mvc (pelajari ini jika ingin tahu mvc) keren
Tutorial mvc (pelajari ini jika ingin tahu mvc) kerenSony Suci
 
Blending Culture in Twitter Client
Blending Culture in Twitter ClientBlending Culture in Twitter Client
Blending Culture in Twitter ClientKenji Tanaka
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
 
Smooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewSmooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewAndrea Prearo
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterKaty Slemon
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Mobivery
 
Using-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUsing-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUadAccount
 
Murach: How to transfer data from controllers
Murach: How to transfer data from controllersMurach: How to transfer data from controllers
Murach: How to transfer data from controllersMahmoudOHassouna
 
Android App Development - 04 Views and layouts
Android App Development - 04 Views and layoutsAndroid App Development - 04 Views and layouts
Android App Development - 04 Views and layoutsDiego Grancini
 
Using a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsUsing a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsallanh0526
 
Vue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexVue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexChristoffer Noring
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptKaty Slemon
 
Arrry structure Stacks in data structure
Arrry structure Stacks  in data structureArrry structure Stacks  in data structure
Arrry structure Stacks in data structurelodhran-hayat
 
reactjs-quiz..docs.pdf
reactjs-quiz..docs.pdfreactjs-quiz..docs.pdf
reactjs-quiz..docs.pdfAyanSarkar78
 

Similar to How to build a debug view almost for free (20)

How to instantiate any view controller for free
How to instantiate any view controller for freeHow to instantiate any view controller for free
How to instantiate any view controller for free
 
Optimize CollectionView Scrolling
Optimize CollectionView ScrollingOptimize CollectionView Scrolling
Optimize CollectionView Scrolling
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOS
 
Swift Tableview iOS App Development
Swift Tableview iOS App DevelopmentSwift Tableview iOS App Development
Swift Tableview iOS App Development
 
Tutorial mvc (pelajari ini jika ingin tahu mvc) keren
Tutorial mvc (pelajari ini jika ingin tahu mvc) kerenTutorial mvc (pelajari ini jika ingin tahu mvc) keren
Tutorial mvc (pelajari ini jika ingin tahu mvc) keren
 
Blending Culture in Twitter Client
Blending Culture in Twitter ClientBlending Culture in Twitter Client
Blending Culture in Twitter Client
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
Smooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewSmooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionView
 
Eclipse Tricks
Eclipse TricksEclipse Tricks
Eclipse Tricks
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
 
Using-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUsing-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptx
 
I os 04
I os 04I os 04
I os 04
 
Murach: How to transfer data from controllers
Murach: How to transfer data from controllersMurach: How to transfer data from controllers
Murach: How to transfer data from controllers
 
Android App Development - 04 Views and layouts
Android App Development - 04 Views and layoutsAndroid App Development - 04 Views and layouts
Android App Development - 04 Views and layouts
 
Using a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsUsing a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS apps
 
Vue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexVue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and Vuex
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
Arrry structure Stacks in data structure
Arrry structure Stacks  in data structureArrry structure Stacks  in data structure
Arrry structure Stacks in data structure
 
reactjs-quiz..docs.pdf
reactjs-quiz..docs.pdfreactjs-quiz..docs.pdf
reactjs-quiz..docs.pdf
 

More from Vincent Pradeilles

The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPathsVincent Pradeilles
 
Solving callback hell with good old function composition
Solving callback hell with good old function compositionSolving callback hell with good old function composition
Solving callback hell with good old function compositionVincent Pradeilles
 
Taking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryTaking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryVincent Pradeilles
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testingVincent Pradeilles
 
Implementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingImplementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingVincent Pradeilles
 
Property Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaProperty Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaVincent Pradeilles
 
Advanced functional programing in Swift
Advanced functional programing in SwiftAdvanced functional programing in Swift
Advanced functional programing in SwiftVincent Pradeilles
 

More from Vincent Pradeilles (10)

On-Boarding New Engineers
On-Boarding New EngineersOn-Boarding New Engineers
On-Boarding New Engineers
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPaths
 
Solving callback hell with good old function composition
Solving callback hell with good old function compositionSolving callback hell with good old function composition
Solving callback hell with good old function composition
 
Taking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryTaking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with Sourcery
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 
Implementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingImplementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional Programing
 
Property Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaProperty Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become Java
 
Cocoa heads 09112017
Cocoa heads 09112017Cocoa heads 09112017
Cocoa heads 09112017
 
Advanced functional programing in Swift
Advanced functional programing in SwiftAdvanced functional programing in Swift
Advanced functional programing in Swift
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
 

Recently uploaded

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 

Recently uploaded (20)

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 

How to build a debug view almost for free

  • 1. How to build a debug view (almost) for free Vincent Pradeilles (@v_pradeilles) & Benoît Caron – Worldline !
  • 3. Why? You have to make sure an app displays properly on the iPhone X, but: • Data is driven by web-services • No mocks are available • More than 150 different screens • Some screens are part of complex business scenarios
  • 4. What would be the right tool?
  • 5. A debug view! • Lists all available UIViewControllers • Indicate a specific use case, if needed • Instantiates, then pushes or presents the controller
  • 6. How do we get the data?
  • 9. The ObjectiveC module • Exposes C APIs to interact with the ObjectiveC runtime • Perfectly OK to use it with Swift
  • 10. The ObjectiveC module func objc_copyClassNamesForImage(_ image: UnsafePointer<Int8>, _ outCount: UnsafeMutablePointer<UInt32>?) -> UnsafeMutablePointer<UnsafePointer<Int8>>? • This function returns a list of all the classes defined in a given bundle • That’s all the data you’ll ever need to build a basic debug view!
  • 11. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 12. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 13. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 14. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 15. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 16. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 17. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 18. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 19. How to use it? extension Bundle { func retrieveAllViewControllers() -> [String] { guard let bundlePath = self.executablePath else { return [] } var viewControllers = [String]() var size: UInt32 = 0 let classes = objc_copyClassNamesForImage(bundlePath, &size) for index in 0..<size { if let className = classes?[Int(index)], let name = NSString.init(utf8String:className) as String?, NSClassFromString(name) is UIViewController.Type { viewControllers.append(name) } } return viewControllers } }
  • 20. How to use it? func instantiateController(named name: String) -> UIViewController? { let controllerClass = NSClassFromString(name) as? UIViewController.Type return controllerClass?.init() }
  • 22.
  • 23. 🎉
  • 24. We’ve just seen the « free » part…
  • 25. …let’s look at the « almost » side of things
  • 26. Providing Initial Data @objc public protocol DebugViewCompliant { func prepareForDebugView() } extension MyViewController: DebugViewCompliant { func prepareForDebugView() { // do some configuration } }
  • 27. Handling Use Cases @objc public protocol DebugViewUseCaseCompliant { static func getUseCases() -> [String] func prepareForDebugView(useCase: String) } extension MyViewController: DebugViewUseCaseCompliant { static func getUseCases() -> [String] { return ["User Not Logged", "User Logged In"] } func prepareForDebugView(useCase: String) { // do some configuration according to `useCase` } }
  • 28. Working with Storyboards @objc public protocol DebugViewInstantiable { static func initForDebugView() -> UIViewController } extension MyViewController: DebugViewInstantiable { static func initForDebugView() -> UIViewController { let storyboard = UIStoryboard(name: "Main", bundle: nil) let viewController = storyboard.instantiateViewController("MyViewController") as! MyViewController return viewController } }
  • 29. Does it work on a real project?
  • 30. Does it work on a real project? YES!
  • 31. How can I use it?
  • 32. How can I use it? • Available on Github : https://github.com/worldline/ControllerFactory • Works with CocoaPods and Carthage • You just need to call: ControllerFactory.instantiate(bundle: Bundle.main) • Only one limitation: it does not work with generic classes 😕
  • 33. 😊