Offline features in iOS are one of the best features which can be utilized when offline syncing data is required. Data can be saved in a persistent manner and utilized in offline mode. Offline Sync can be a push and pull the data from the server. Auto syncing data when a user comes offline to online mode. Offline is useful when the user needs the data when network connectivity goes So developer need to design the iOS app development services in such a way that all the data can be saved in the offline mode inside core data, cache and in the file system but most of cases developer used to saved data in core data because it can accommodate large data
Library to handle Offline
- Networking
- Coredata
- Keychain
Offline data can be saved in various places iOS
- Property List
- SQLite
- Core Data
- NSUser Defaults
- Key Chain
Benefit of Offline
- Auto Sync data
- Pull and Push data
- Data saved offline and access online
- Cache and database can be used for offline
- Offline to Online syncing
Offline implementation using Reachability
1.Identifier for the notifications triggered by Reachability Online Offline. The Notification info will contain a dictionary with the keyReachabilityStatusOfflineOnlineChangedthat will contain a description of the current connection status. Closure type definition for ReachabilityOnlineOffline status updates
public let ReachabilityOnlineOfflineDidChangeNotification = “com.xyz.ReachabilityOnlineOffline.change”
public typealiasReachabilityOnlineOfflineClosure = (_ reachable: Bool, _ status: ReachabilityStatusOfflineOnline) -> Void
2.Enum with the possible status of the internet connection monitored byReachabilityOnlineOffline
public enumReachabilityStatusOfflineOnline
{
case notReachable
case reachableViaWWan
case reachableViaWifi
public var description: String {
switch self
{
case .reachableViaWWan:
return “ReachableViaWWan”
case .reachableViaWifi:
return “ReachableViaWifi”
case .notReachable:
return “NotReachable”
}
}
}
3. Class for monitoring if an internet connection is present. Var for accessing the ReachabilityOnlineOffline singleton the default host for monitoring reachability is “XYZ.com”.This var holds a closure for receiving reachability changes. Var for verifying if the internet is reachable. Var with information about the current internet connection
public class ReachabilityOnlineOffline {
private var _isReachable: Bool = false
private var _reachabilityStatus: ReachabilityStatusOfflineOnline = .notReachable
private var scNetworkReachability: SCNetworkReachability?
public static let instance = ReachabilityOnlineOffline()
public var reachabilityClosure: ReachabilityOnlineOfflineClosure?
public var isReachable: Bool {
return self._isReachable
}
public var reachabilityStatus: ReachabilityStatusOfflineOnline {
return self._reachabilityStatus
}
private init() {
let defaultHost = “xyz.com”
guard let addressReachability = ReachabilityOnlineOffline.createReachabilityWithHost(defaultHost) else {
return
}
self.scNetworkReachability = addressReachability
}
3. Reachability with address need to check to reachability
private static funccreateReachabilityWithAddress(_ address: sockaddr_in) ->SCNetworkReachability? {
var addr = address
guard let networkReachability = withUnsafePointer(to: &addr, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return nil
}
return networkReachability
}
4. Reachability with host needs to found and Reachability can check whether wifi connected or not whether it is offline or online. If it is offline then not reachbale wiil come where data can be saved
private static funccreateReachabilityWithHost(_ host: String) ->SCNetworkReachability? {
let hostToReach = host
var host = hostToReach
guard let networkReachability = withUnsafePointer(to: &host, {_ in
SCNetworkReachabilityCreateWithName(nil, hostToReach)
}) else {
return nil
}
return networkReachability
}
private static funcstatusFromReachabilityFlags(_ flags: SCNetworkReachabilityFlags) ->ReachabilityStatusOfflineOnline {
var status: ReachabilityStatusOfflineOnline
let isConnectionRequired = flags.contains(.connectionRequired)
let isReachable = flags.contains(.reachable)
let isReachableViaWwan = flags.contains(.isWWAN)
if !isConnectionRequired&&isReachable {
if isReachableViaWwan {
status = .reachableViaWWan
} else {
status = .reachableViaWifi
}
} else {
status = .notReachable
}
return status
}
private static funcisReachableFromStatus(_ status: ReachabilityStatusOfflineOnline) -> Bool {
switch status {
case .reachableViaWifi:
return true
case .reachableViaWWan:
return true
default:
return false
}
}
private static funchandleReachabilityStatusUpdate(_ pointer: UnsafeMutableRawPointer, isReachable: Bool, reachabilityStatus: ReachabilityStatusOfflineOnline) {
let selfInstance = Unmanaged<ReachabilityOnlineOffline>.fromOpaque(pointer).takeUnretainedValue()
selfInstance._isReachable = isReachable
selfInstance._reachabilityStatus = reachabilityStatus
NotificationCenter.default.post(name: Notification.Name(rawValue: ReachabilityOnlineOfflineDidChangeNotification),
object: nil,
userInfo: [“ReachabilityStatusOfflineOnlineChanged”: reachabilityStatus.description])
DispatchQueue.main.async(execute: { () -> Void in
selfInstance.reachabilityClosure?(selfInstance.isReachable,
selfInstance.reachabilityStatus)
})
}
private funcgetReachabilityFlags() ->SCNetworkReachabilityFlags? {
guard let reachability = scNetworkReachability else {
return nil
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(reachability, &flags) {
return nil
}
return flags
}
5. A method that starts monitoring reachability of the default address, a custom host or custom address For setting a host for reachability, call setHostForReachability and supply a host as String, ie: “xyz.com”. For setting a custom address for reachability, call setAddressForReachability and supply a sockaddr_in with the address or monitoring reachability
public funcstartMonitoring() {
self.stopMonitoring()
guard let reachability = self.scNetworkReachability else {
self._isReachable = isReachable
self._reachabilityStatus = reachabilityStatus
return
}
var scNetworkContext = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
scNetworkContext.info = UnsafeMutableRawPointer(Unmanaged.passRetained(self).toOpaque())
SCNetworkReachabilitySetCallback(reachability, { (reachability, flags, info) in
let reachabilityStatus = ReachabilityOnlineOffline.statusFromReachabilityFlags(flags)
let isReachable = ReachabilityOnlineOffline.isReachableFromStatus(reachabilityStatus)
let selfInstance = Unmanaged<ReachabilityOnlineOffline>.fromOpaque(info!).takeUnretainedValue()
if selfInstance.isReachable != isReachable {
ReachabilityOnlineOffline.handleReachabilityStatusUpdate(info!,
isReachable: isReachable,
reachabilityStatus: reachabilityStatus)
}
},
&scNetworkContext)
SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
}
6. Stops ReachabilityOnlineOffline of monitoring for internet connection changes
public funcstopMonitoring() {
guard let reachability = self.scNetworkReachability else {
return
}
SCNetworkReachabilityUnscheduleFromRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
}
7. Sets a host for monitoring reachability, when this method is called, reachability monitoring is stopped. You should call startMonitoring() after setting a new host
– parameter host: a host for monitoring reachability with the format “host.domain” ie: “xyz.com”
public funcsetHostForReachability(_ host: String) {
self.stopMonitoring()
self.scNetworkReachability = nil
guard let hostReachAbility = ReachabilityOnlineOffline.createReachabilityWithHost(host) else {
return
}
self.scNetworkReachability = hostReachAbility
}
8. Sets an address for monitoring reachability, when this method is called, reachability monitoring is stopped you should call startMonitoring() after setting a new address – parameter address: an address for monitoring reachability with the format “host.domain” ie: “xyz.com”
public funcsetAddressForReachability(_ address: sockaddr_in) {
self.stopMonitoring()
self.scNetworkReachability = nil
guard let addressReachability = ReachabilityOnlineOffline.createReachabilityWithAddress(address) else {
return
}
self.scNetworkReachability = addressReachability
}
9. Perform a synchronous check to determine the current reachabillity state via reachability flags.
- parameter shouldNotify: a Boolean value to indicate whether the application should be notified via the usual channels (notification, closure) if a change in reachability is detected via synchronous check
- Returns: boolean value indicative of whether device is considered reachable based on reachability flags
public funcperformSynchronousReachabilityCheck(shouldNotify: Bool) -> Bool {
guard let reachabilityFlags = getReachabilityFlags() else { return false }
let reachabilityStatus = ReachabilityOnlineOffline.statusFromReachabilityFlags(reachabilityFlags)
let isReachable = ReachabilityOnlineOffline.isReachableFromStatus(reachabilityStatus)
if shouldNotify, self.isReachable != isReachable {
self._isReachable = isReachable
self._reachabilityStatus = reachabilityStatus
NotificationCenter.default.post(name: Notification.Name(rawValue: ReachabilityOnlineOfflineDidChangeNotification),
object: nil,
userInfo: [“ReachabilityStatusOfflineOnlineChanged”: reachabilityStatus.description])
DispatchQueue.main.async(execute: { () -> Void in
self.reachabilityClosure?(self.isReachable,
self.reachabilityStatus)})
}
return isReachable
}
}