newnode
newnode copied to clipboard
iOS: Extract network extension management into a separate file
This is the first step of the ViewController
refactoring process described in #139
All the network extension stuff is now moved into a separate component and the ViewController
's dependency graph changed from this
flowchart LR
viewController --> UIViewController
viewController --> UIButton
viewController --> UIImageView
viewController --> UILabel
viewController --> UserDefaults
viewController --> NotificationCenter
viewController --> MMWormhole
viewController --> NETunnelProviderManager
viewController --> NWPathMonitor
viewController --> NEVPNStatus
subgraph User Iinterface
UIButton
UIImageView
UILabel
UIViewController
end
subgraph Infrastructure
UserDefaults
NotificationCenter
MMWormhole
end
subgraph Networking
NETunnelProviderManager
NWPathMonitor
NEVPNStatus
end
to this:
flowchart RL
viewController --> UIViewController
viewController --> UIButton
viewController --> UIImageView
viewController --> UILabel
viewController --> UserDefaults
viewController --> NotificationCenter
viewController --> MMWormhole
TunnelManagerImpl --> NETunnelProviderManager
TunnelManagerImpl --> NEVPNStatus
TunnelManagerImpl -.-> TunnelManager["<TunnelManager>"]
TunnelManagerDelegate --> TunnelManagerState
viewController --> TunnelManager
viewController --> TunnelManagerDelegate
subgraph User Interface
UIButton
UIImageView
UILabel
UIViewController
end
subgraph Infrastructure
UserDefaults
NotificationCenter
MMWormhole
end
subgraph Network Extension
NETunnelProviderManager
NWPathMonitor
NEVPNStatus
end
subgraph NewNode
TunnelManager
TunnelManagerDelegate
TunnelManagerState
TunnelManagerImpl
end
There are some benefits of this approach:
-
ViewController
does not depend on NetworkExtension, the dependency inversion principle applied -
TunnelManager
can be shared between iOS/macOS platforms without any change - We can have multiple implementations for the
TunnelManager
protocol which allows us to focus on UI improvements on the simulator. Like so:
private lazy var tunnelManager: TunnelManager = {
#if targetEnvironment(simulator)
TunnelManagerSimulator(delegate: self)
#else
TunnelManagerImpl(delegate: self)
#endif
}()
- No need to use
NWPathMonitor
since we can rely onNWConnection
state - Fixed bug when the connection fails after another VPN enabled