SlideShare a Scribd company logo
Medium TechTalk — iOS
Medium TechTalk — iOS
Medium TechTalk — iOS
How might we create a
simple and intuitive mobile
consumption experience
for Medium?
Medium TechTalk — iOS
How might we create a
simple and intuitive
mobile consumption
experience for Medium?
How might we create a
delightful, simple and intuitive
mobile consumption
experience for Medium?
Medium TechTalk — iOS
Medium TechTalk — iOS
Medium TechTalk — iOS
Medium TechTalk — iOS
Medium TechTalk — iOS
History stack Future stack
Cover Flow
<html>?
Medium TechTalk — iOS
Medium TechTalk — iOS
Medium TechTalk — iOS
• 60 FPS
• Memory
• Parallax
UIKit &
TextKit
{	
"content": {	
...	
"bodyModel": {	
"elements": <Elements>,	
"sections": <Sections>	
},	
...	
},	
}
{	
"name": "8419",	
"type": 1,	
"text": "...song Walking in LA?",	
"markups": [	
{	
"type": 3,	
"start": 300,	
"end": 315,	
"href": "https://somewhere.com",	
"title": "",	
"rel": ""	
}	
]	
}
{	
"name": "24cc",	
"type": 4,	
"text": "",	
"markups": [],	
"layout": 1,	
"metadata": {	
"id": "1*WwSQ20QNvf-WovuMLLslEA.jpeg",	
"originalWidth": 453,	
"originalHeight": 301	
}	
}
{	
"name": "38d2",	
"startIndex": 6	
}
{	
"name": "7b28",	
"startIndex": 31,	
"backgroundImage": {	
"id": "1*DhgXe8j0YqltMNM6-pRy6Q.jpeg",	
"originalWidth": 1920,	
"originalHeight": 1200	
},	
"textLayout": 2,	
"imageLayout": 2	
}
CoverFlowView
CoverFlowView
PostView
CoverFlowView
PostView
SectionView
CoverFlowView
PostView
SectionView
SectionImageView
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
CoverFlowView
PostView
SectionView
SectionContentView
ElementElementElement
SectionImageView
CoverFlowView
PostView
SectionView
SectionContentView
ElementElementElement
SectionImageView
CoverFlowView
PostView
SectionView
SectionContentView
ElementElementElement
SectionImageView
Element
CoverFlowView
PostView
SectionView
SectionContentView
ElementElementElement
SectionImageView
Element
CoverFlowView
PostView
SectionView
SectionContentView
ElementElement
SectionImageView
Element
CoverFlowView
PostView
SectionView
SectionContentView
ElementElement
SectionImageView
Element
Sect
Section
SectionC
Elemen
CoverFlowView
PostView
View
ntentView
ent
ageView
Element
SectionView
SectionImageView
SectionContentView
ElementElement
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
ElementElement
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
ElementElement
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
ElementElement
Sect
Section
CoverFlowView
PostView
View
ageView
ntentView
lement
SectionView
SectionImageView
SectionC
Elemen
CoverFlowView
PostView
SectionView
SectionImageView
SectionC
Elemen
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
Element
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
ElementElement
CoverFlowView
PostView
SectionView
SectionImageView
SectionContentView
ElementElement
Thank You!
Questions?
!
Grant Oladipo
grant@medium.com
@kocodude
Shapes & things
Building the data layer of the Medium iOS app
!
!
Elizabeth Ford
@infraredflower
Medium TechTalk — iOS
Title
Body text
Other stuff
User
!
Collection
User’s name
Bio
List of stories
• How will we deal with the possibility of API
changes?
• especially since the app will be long-lived
• How do we minimize the number of requests
from the iOS app to the server?
• How can we avoid making separate API routes
for the iOS app (and every client thereafter)?
Questions…
Clearly bad ideas
• Make multiple requests to display
one Post, User, or Collection
• Make new iOS routes with exactly
what we need
• Only save full objects
Clearly bad ideas
• Save partial objects and if we need a
full object, just check to see if all the
fields are set in the object in the
cache
• Is the field supposed to be “” or
was it never set?
Speaking of which…
• How should we deal with
merging two objects?
• Merging a full post and
a partial post
Example
Shapes!
Shapes!
Saving objects
Merging objects
Complexity hidden by data layer
• merges objects
• determines when to make
network requests
Complexity hidden by data layer
What about dealing with a changing API?
• explicit definitions for the
resources returned by API
endpoints
• tests based on these definitions
Possible areas for improvement
• one service to return any shape
(instead of a separate data
service for each type of object)
• autogenerate shape definitions
from protocol buffers (on both
server and client)
• easy to add features on the iOS side
• easy to make changes on the server
side without breaking the iOS client
• minimize # of server requests
Shapes!
Thank You!
Questions?
!
Elizabeth Ford
eford@medium.com
@infraredflower
Meet the Singletons
Jimmy O’Neill
Engineer, Medium
@jmyonl
+ (id)sharedResource {
static id _instance;
static dispatch_once_t onceToken;
!
dispatch_once(&onceToken, ^{
_instance = [[Resource alloc] init];
});
!
return _instance;
}
A singleton restricts the instantiation of a class to one object.
They are often lazily instantiated.
They can be accessed globally by any module of a program.
UIApplication
NSFileManager
NSNotificationCenter
NSURLSession
Since singletons are so commonplace in CocoaTouch, many developers overuse them.
A lot of this:
Singletons are bad!!
!
Not a lot of this:
Singletons can be bad because ____. Here’s a real example!
!
!
!
I’m going to focus on this:
Singletons can be bad because ____. Here’s a real example!
Medium TechTalk — iOS
- (AuthCredential *)mediumAuthCredential;
!
- (void)saveMediumAuthCredential:(AuthCredential *)credential;
AuthCredentialDataService
Keychain
AuthCredentialDataService
- (void)fetch:(NetRequest *)request
completion:(void (^)(NetResponse *, NSError *))completion;
Net
AuthCredentialDataService
NetNet
- (void)fetchPostById:(NSString *)postId
completion:(void(^)(Post *post, NSError *error))completion;
PostService
Net
AuthCredentialDataService
PostService
- (void)fetchPostViewDataWithPostId:(NSString *)postId
completion:(void(^)(Post *post,
PostViewModel *postViewModel,
PostUserData *postUserData,
NSError *error))callback;
PostViewService
PostService
Net
AuthCredentialDataService
PostViewService
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService
PostViewController
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService
PostViewController
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService
Data dependence
Time dependence
AuthCredentialDataService
PostViewController
Time dependence isn’t an
issue until the underlying
data starts changing.
PostViewController
PostViewService
PostService
Net
AuthCredentialDataServiceAuthCredentialDataService
PostViewController
If your app supports sign out,
the underlying authentication
data is changing.
PostViewController
PostViewService
PostService
Net
AuthCredentialDataServiceAuthCredentialDataService
PostViewController
What problems does time
dependence cause?
- Functional impurity
- Leaky abstraction
- Background task failures
- Difficult to test
PostViewController
PostViewService
PostService
Net
AuthCredentialDataServiceAuthCredentialDataService
PostViewController
Example.
PostViewController
PostViewController
Medium TechTalk — iOS
LoginViewController
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged in
1. User bookmark action is queued
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged in
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
4. Bookmark request 401s
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
4. Bookmark request 401s
5. PostViewController is cleaned up
PostViewService
PostService
Net
AuthCredentialDataService Logged out
LoginViewController
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId];
});
How do we fix this?
Option 1: YOLO
Advantages!
- Very little work
- No testing needed
- Funny later in your career
Disadvantages!
- Horrible UX
- Async bookmark operation still fails
- (void)logOut {
// nuke everything
exit(0);
}
Option 2: Embrace time dependence
Advantages!
- Doesn’t require refactoring
Disadvantages!
- Requires global knowledge of all the apps components
- Affects other, disjunct service consumers
- Difficult to test
- Async bookmark operation still fails
- (void)logOut {
// Synchronously wipe all the user-dependent data
[[Services authCredentialDataService] wipeData];
// …
!
// Reload UI with new global data
[_appController reload];
}
Option 3: Dependency inject your user-dependent data
- Eliminates time dependence in the service layer
- Gracefully supports switching authentication contexts
- Easy to test interfaces with a mock Session object
- Async bookmark operation succeeds
- (void)logOut {
// Create an unauthenticated session
Session *newSession = [Session loggedOutSession];
!
// Reload UI with logged out session
[_appController loadSession:newSession];
}
@interface Session : NSObject
!
- (instancetype)initWithAuth:(AuthCredential *)authCredential;
!
@property (nonatomic, strong, readonly) NSString *sessionId;
@property (nonatomic, strong, readonly) AuthCredential *authCredential;
!
- (BOOL)isAuthenticated;
!
@end
The Session object directly models user-dependent state,
and is injected into objects that need it.
- (void)fetch:(NetRequest *)request
completion:(void (^)(NetResponse *, NSError *))completion;
Net
AuthCredentialDataService
Net
Net
AuthCredentialDataService
Net
Session
Net
Net
Net
Session
- (void)fetch:(NetRequest *)request
session:(Session *)session
completion:(void (^)(NetResponse *, NSError *))completion;
Net
PostService
Net
Session
- (void)fetchPostById:(NSString *)postId
session:(Session *)session
completion:(void(^)(Post *post, NSError *error))completion;
PostService
PostViewService
PostService
Session
Net
- (void)fetchPostViewDataWithPostId:(NSString *)postId
session:(Session *)session
completion:(void(^)(Post *post,
PostViewModel *postViewModel,
PostUserData *postUserData,
NSError *error))callback;
PostViewService
PostViewService
PostService
Net
PostViewController
Session
[[PostViewController alloc] initWithPostId:postId
session:session];
PostViewController
Session
PostViewController
PostViewController
Medium TechTalk — iOS
LoginViewController
1. User bookmark action is queued
PostViewService
PostService
Net
PostViewController
Logged in
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
PostViewService
PostService
Net
PostViewController
Logged in
Session
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewService
PostService
Net
PostViewController
Logged in
Session
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewService
PostService
Net
PostViewController
Logged in
Session
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
PostViewService
PostService
Net
PostViewController
Logged in
Session
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
4. Bookmark action succeeds
PostViewService
PostService
Net
PostViewController
Logged in
Session
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
1. User bookmark action is queued
2. User signs out
3. Bookmark action is dequeued
4. Bookmark action succeeds
5. PostViewController and logged in
Session are cleaned up
PostViewService
PostService
Net
LoginViewController
Logged out
Session
dispatch_async(_backgroundQueue, ^{
[[Services postView] bookmark:_postId session:_session];
});
Think back to the original decision.
Net
AuthCredentialDataService
Keychain
Net
It appears innocent without context.
Net
AuthCredentialDataService
Keychain
Net
Let’s do our best to recognize!
the larger context earlier.
PostViewController
PostViewService
PostService
Net
AuthCredentialDataService
Data dependence
Time dependence
AuthCredentialDataService
PostViewController
Singletons are global state.
Singletons assume that the lifetime of the state they encapsulate is equal
to the lifetime of the program.
Singletons are not evil.
But often, dependency injection is a sounder option.
Thank You!
Questions?
!
Jimmy O’Neill
jimmy@medium.com
@jmyonl
Designing an iOS
Distribution Pipeline
Vinicius Baggio Fuentes
Delivery on the Web
• Feature Toggle
• Tracking and measuring
• Rolling releases
• Multiple deploys a day
Short deployment time
is key
How can we do the
same for apps?
Challenges
• Pre-App Store distribution is complicated
• Slow response time on App Store approvals
Fast release requirements
• Over-the-air updates
• Crash report system
• Authorization server
• Feature toggles
• Versioning system
• Distribution channels
OTA updates, crash reports
and authorization
• Crashlytics
• TestFlight / Apple’s upcoming beta program
• HockeyApp
Feature toggle
• A/B Testing
• Long running feature development
• Emergencies
VARIANT_ENABLE_RECOMMEND_NOTES_COMPOSITION
Feature toggle tools
• GroundControl, SkyLab & related
projects
• Roll-your-own (not recommended)
Versioning system:

semantic versioning
master 640a0a5 638b3b7
master 640a0a5
build-1.3
638b3b7
dde3123
build-1.3.0
master 640a0a5
build-1.3
638b3b7 03dc0b5
dde3123
build-1.3.0
master 640a0a5
build-1.3
638b3b7 03dc0b5 4aee8cd
dde3123 bb24c74
build-1.3.0
master 640a0a5
build-1.3
638b3b7 03dc0b5 4aee8cd 04d773b
dde3123 bb24c74 f1e48af
build-1.3.1
build-1.3.0
master 640a0a5
build-1.3
build-1.4
638b3b7 03dc0b5 4aee8cd 04d773b
dde3123 bb24c74 f1e48af
build-1.3.1
f1e48af
build-1.3.0
build-1.4.0
Distribution channels
Distribution channels
Developers Medium Staff
On merge
Version 1.4.90
Distribution channels
Version 1.4.90
Developers Medium Staff Trusted testers
On merge After a day
Distribution channels
Version 1.4.90
Developers Medium Staff Trusted testers Beta testers
On merge After a day After a week
Lessons Learned
• Xcconfig files and -derivedDataPath compiler
flag helps builds being deterministic
• Plist manipulation in Python, nomad-cli tools (esp.
Shenzhen, Cupertino)
Xcconfig example
#include "base.xcconfig"
#include "Servers/medium.xcconfig"
#include "Build/config-debug.xcconfig"
!
MEDIUM_DISTRIBUTION_CHANNEL = mediumStaff
Lessons Learned [2]
• Make it easy for everyone to see which version of
the app each group has
• Easy visibility and communication on features of
each of these groups
• Automate everything, consider Jenkins CI over
Xcode Bots
Thanks!
• References:
• www.nomad-cli.com
• jenkins-ci.org
• crashlytics.com
• https://github.com/mattt/GroundControl
• http://semver.org
• hockeyapp.net
• http://techcrunch.com/2014/06/02/ios-testflight/
Vinícius Baggio Fuentes
vinny@medium.com
@vinibaggio
Thanks for coming!

More Related Content

PDF
PDF
MVS: An angular MVC
PPTX
e-suap - client technologies- english version
PPTX
Angular js 1.0-fundamentals
PPTX
SFDC Inbound Integrations
PPTX
Getting Started with jQuery
PDF
How To Manage API Request with AXIOS on a React Native App
PPT
Backbone js
MVS: An angular MVC
e-suap - client technologies- english version
Angular js 1.0-fundamentals
SFDC Inbound Integrations
Getting Started with jQuery
How To Manage API Request with AXIOS on a React Native App
Backbone js

What's hot (20)

ODP
Spray - Build RESTfull services in scala
PDF
Advanced SharePoint 2010 and 2013 Web Part Development by Rob Windsor - SPTec...
PPTX
Getting Started with Javascript
PDF
Angular 2 Component Communication - Talk by Rob McDiarmid
PPTX
MSFT Dumaguete 061616 - Building High Performance Apps
PPTX
Advanced SharePoint Web Part Development
PDF
iOS 7 SDK特訓班
PDF
MAF push notifications
KEY
Building Web Service Clients with ActiveModel
PDF
Distributing information on iOS
PDF
In memory OLAP engine
PDF
HTML5 New and Improved
PDF
Lecture 3: Servlets - Session Management
PPTX
Lyudmila Zharova: Developing Solutions for SharePoint 2010 Using the Client O...
PDF
Jasigsakai12 columbia-customizes-cas
PPTX
Use Windows Azure Service Bus, BizTalk Services, Mobile Services, and BizTalk...
PDF
Breaking the limits_of_page_objects
PDF
Apex Code Analysis Using the Tooling API and Canvas
PDF
Silverlight 2 For Developers
PPTX
Using the Tooling API to Generate Apex SOAP Web Service Clients
Spray - Build RESTfull services in scala
Advanced SharePoint 2010 and 2013 Web Part Development by Rob Windsor - SPTec...
Getting Started with Javascript
Angular 2 Component Communication - Talk by Rob McDiarmid
MSFT Dumaguete 061616 - Building High Performance Apps
Advanced SharePoint Web Part Development
iOS 7 SDK特訓班
MAF push notifications
Building Web Service Clients with ActiveModel
Distributing information on iOS
In memory OLAP engine
HTML5 New and Improved
Lecture 3: Servlets - Session Management
Lyudmila Zharova: Developing Solutions for SharePoint 2010 Using the Client O...
Jasigsakai12 columbia-customizes-cas
Use Windows Azure Service Bus, BizTalk Services, Mobile Services, and BizTalk...
Breaking the limits_of_page_objects
Apex Code Analysis Using the Tooling API and Canvas
Silverlight 2 For Developers
Using the Tooling API to Generate Apex SOAP Web Service Clients
Ad

Viewers also liked (13)

PDF
อุปกรณ์เชื่อมต่อคอมพิวเตอร์
PPTX
A importância da qualidade de software e suas diversas perspectivas
PDF
Cuadro comparativo
PDF
Ortografia letras grupo_hache
PPTX
Diapositivas expo ingles
PDF
SR Graduation Gifts
PDF
Preparing for Year End workshop
PPTX
prawphan
PPSX
CiNEMAN-On.ADs DETAIL
PDF
Green presentatie graafschap college
PPTX
Технологии анализа бинарного кода приложений: требования, проблемы, инструменты
PDF
Big data summary_v2.1
PDF
Serie escribo-letras-y-numeros-libros-dismes-muestras-gratuitas
อุปกรณ์เชื่อมต่อคอมพิวเตอร์
A importância da qualidade de software e suas diversas perspectivas
Cuadro comparativo
Ortografia letras grupo_hache
Diapositivas expo ingles
SR Graduation Gifts
Preparing for Year End workshop
prawphan
CiNEMAN-On.ADs DETAIL
Green presentatie graafschap college
Технологии анализа бинарного кода приложений: требования, проблемы, инструменты
Big data summary_v2.1
Serie escribo-letras-y-numeros-libros-dismes-muestras-gratuitas
Ad

Similar to Medium TechTalk — iOS (20)

PDF
Elements for an iOS Backend
PDF
Maintaining a dependency graph with weaver
PDF
303 TANSTAAFL: Using Open Source iPhone UI Code
PDF
3 Mobile App Dev Problems - Monospace
PDF
iOS Bootcamp: learning to create awesome apps on iOS using Swift (Lecture 7)
PDF
Concurrent networking - made easy
PDF
Design Pattern Cheatsheet
KEY
Effective iOS Network Programming Techniques
ZIP
iPhone and Rails integration
PDF
REST/JSON/CoreData Example Code - A Tour
PDF
Chaplin.js in real life
KEY
Speedupiosdevelopment
PDF
Hızlı Cocoa Geliştirme (Develop your next cocoa app faster!)
PDF
iOS 2 - The practical Stuff
PPTX
Hypermedia System Architecture for a Web of Things
PDF
MFF UK - Advanced iOS Topics
PDF
AfNetworking vs. Native + Caching
PDF
Synchronizing without internet - Multipeer Connectivity (iOS)
PDF
Três conceitos que farão a diferença nos seus apps
PPTX
04 objective-c session 4
Elements for an iOS Backend
Maintaining a dependency graph with weaver
303 TANSTAAFL: Using Open Source iPhone UI Code
3 Mobile App Dev Problems - Monospace
iOS Bootcamp: learning to create awesome apps on iOS using Swift (Lecture 7)
Concurrent networking - made easy
Design Pattern Cheatsheet
Effective iOS Network Programming Techniques
iPhone and Rails integration
REST/JSON/CoreData Example Code - A Tour
Chaplin.js in real life
Speedupiosdevelopment
Hızlı Cocoa Geliştirme (Develop your next cocoa app faster!)
iOS 2 - The practical Stuff
Hypermedia System Architecture for a Web of Things
MFF UK - Advanced iOS Topics
AfNetworking vs. Native + Caching
Synchronizing without internet - Multipeer Connectivity (iOS)
Três conceitos que farão a diferença nos seus apps
04 objective-c session 4

Recently uploaded (20)

PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Complete Guide to Website Development in Malaysia for SMEs
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
PPTX
assetexplorer- product-overview - presentation
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Transform Your Business with a Software ERP System
PDF
Cost to Outsource Software Development in 2025
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Designing Intelligence for the Shop Floor.pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
17 Powerful Integrations Your Next-Gen MLM Software Needs
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Design an Analysis of Algorithms I-SECS-1021-03
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Complete Guide to Website Development in Malaysia for SMEs
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
assetexplorer- product-overview - presentation
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Transform Your Business with a Software ERP System
Cost to Outsource Software Development in 2025
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Designing Intelligence for the Shop Floor.pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
Monitoring Stack: Grafana, Loki & Promtail
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Reimagine Home Health with the Power of Agentic AI​
Oracle Fusion HCM Cloud Demo for Beginners
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
17 Powerful Integrations Your Next-Gen MLM Software Needs
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Design an Analysis of Algorithms I-SECS-1021-03

Medium TechTalk — iOS