Skip to content

Instantly share code, notes, and snippets.

@mspvirajpatel
Last active August 20, 2017 07:58
Show Gist options
  • Save mspvirajpatel/ad8aee9821fe61d94925c438ef712f2c to your computer and use it in GitHub Desktop.
Save mspvirajpatel/ad8aee9821fe61d94925c438ef712f2c to your computer and use it in GitHub Desktop.
Image Upload Manager with Almofire and Create With Model
import UIKit
import SystemConfiguration
import UserNotifications
class AppUtility: NSObject {
// MARK: - Network Connection Methods
class func isNetworkAvailableWithBlock(_ completion: @escaping (_ wasSuccessful: Bool) -> Void) {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
completion(false)
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
completion(isReachable && !needsConnection)
}
}
import UIKit
import Alamofire
// MARK: - API Task Constant -
enum APITask : String
{
case UploadAllImages = "Upload Image"
}
enum Result {
case Success(response : AnyObject?,error : BaseError?)
case Error(error : BaseError?)
case Internet(isOn : Bool)
}
class BaseAPICall: NSObject
{
class var shared: BaseAPICall
{
struct Static
{
static var instance: BaseAPICall?
}
let _onceToken = NSUUID().uuidString
DispatchQueue.once(token: _onceToken) {
Static.instance = BaseAPICall()
}
return Static.instance!
}
func uploadImage (url: String, Parameter param : NSDictionary, Images arrImage: NSArray, Type type : APITask , completionHandler : @escaping (_ result : Result) -> ()) -> Void
{
AppUtility.isNetworkAvailableWithBlock { (isAvailable) in
if isAvailable == true{
completionHandler(Result.Internet(isOn: true))
var requestURL : String! = APIConstant.baseURL + url
let headers = [
"Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
"Accept": "application/json"
]
print("---------------------")
print("\(type.rawValue) request :- \(param .JSONString())")
print("Request URL :- \(requestURL)")
print("---------------------")
Alamofire.upload(multipartFormData: { (data) in
for (key, value) in param {
data.append((value as! String).data(using: .utf8)!, withName: key as! String)
}
for imageInfo in arrImage
{
var dicInfo : NSDictionary! = imageInfo as! NSDictionary
data.append(dicInfo["data"] as! Data, withName: dicInfo["name"] as! String, fileName: dicInfo["fileName"] as! String, mimeType: dicInfo["type"] as! String)
dicInfo = nil
}
}, to: requestURL, method: .post , headers:nil, encodingCompletion: { (encodeResult) in
switch encodeResult {
case .success(let upload, _, _):
upload.responseJSON(completionHandler: { (response) in
switch response.result
{
case .success(let responseJSON):
guard let dicResponse = responseJSON as? NSDictionary else{
return
}
print("Response : \((dicResponse) .JSONString())")
var handledResopnse : (BaseError? , AnyObject?)! = self.handleResponse(response: dicResponse, task: type)
if handledResopnse.1 != nil{
completionHandler(Result.Success(response: handledResopnse.1, error: handledResopnse.0))
}
else{
completionHandler(Result.Error(error: handledResopnse.0))
}
defer{
handledResopnse = nil
}
case .failure(let error):
print(error)
completionHandler(Result.Error(error: self.handleFailure(error: error)))
break
}
})
case .failure(let error):
completionHandler(Result.Error(error: self.handleFailure(error: error)))
break
}
})
}
else{
completionHandler(Result.Internet(isOn: false))
}
}
}
private func handleResponse(response : AnyObject,task : APITask) -> (BaseError? , AnyObject?){
var baseError : BaseError! = BaseError.getError(responseObject: response, task: task)
if baseError.errorCode == "1" || baseError.errorCode == "200"{ // 1 is success code, here we need to set success code as per project and api backend. its may 1 or 200, depend on API
var modelResponse : AnyObject! = MainResponse().getModelFromResponse(response: response , task: task)
defer{
modelResponse = nil
baseError = nil
}
return (baseError,modelResponse)
}
else{
defer{
baseError = nil
}
return (baseError, nil)
}
}
private func handleFailure(error : Error) -> BaseError{
print("Error : \(error.localizedDescription)")
var baseError : BaseError! = BaseError()
switch error._code{
case NSURLErrorTimedOut:
baseError.errorCode = String(error._code)
baseError.alertMessage = "Server is not responding please try again after some time."
baseError.serverMessage = "Server is not responding please try again after some time."
break
case NSURLErrorNetworkConnectionLost:
baseError.errorCode = String(error._code)
baseError.alertMessage = "Network connection lost try again."
baseError.serverMessage = "Network connection lost try again."
break
default:
baseError.errorCode = String(-1)
baseError.alertMessage = "Something wants wrong please try again leter."
baseError.serverMessage = "Something wants wrong please try again leter."
break
}
defer{
baseError = nil
}
return baseError
}
}
import Foundation
class BaseError: NSObject {
// MARK: - Attributes -
var errorCode: String = ""
var serverMessage: String = ""
var alertMessage: String = ""
// MARK: - Lifecycle -
deinit{
}
// MARK: - Public Interface -
class func getError(responseObject: AnyObject , task : APITask) -> BaseError{
let error: BaseError = BaseError()
if let code = responseObject["error_code"] as? Int
{
error.errorCode = String(code)
}
else{
error.errorCode = (responseObject["error_code"] as? String)!
}
if(error.errorCode == ""){
error.errorCode = "1";
}
if let code = responseObject["message"] as? String
{
error.serverMessage = String(code)
}
else{
error.serverMessage = ""
}
error.alertMessage = error.serverMessage;
print("---------------------");
print("Request Type: %@", task.rawValue);
print("Error Code: %@", error.errorCode);
print("Server Message: %@", error.serverMessage);
print("Alert Message: %@", error.alertMessage);
print("---------------------");
return error
}
// MARK: - Internal Helpers -
}
//Add Images in Upload Manager
var arrImage : [UIImage]? = []
let isUploadAdded : Bool = ImageUploadManager.sharedInstance.addImageForUpload(arrImage: arrImage!)
if isUploadAdded
{ print("new Image Added") }
//Get Image Upload Progress
ImageUploadManager.sharedInstance.setUpdateProgressStatusEven { (wasSuccessfull, object) in
let arrCount : NSArray = object as! NSArray
lblProgress.text = "Uploading (\(arrCount[0])\\\(arrCount[1]))"
let uploadedImg : Float = Float(arrCount[0] as! Int)
let totalImg : Float = Float(arrCount[1] as! Int)
print("Completed : \(String(describing: arrCount.firstObject))" , "Total : \(arrCount[1])")
print("Progress : \(uploadedImg / totalImg)")
if arrCount[0] as! Int == arrCount[1] as! Int
{
print("Upload is completed...")
}
}
import UIKit
class ImageUploadManager: NSObject
{
// MARK: - Attributes -
fileprivate var isUploadingRunning : Bool = false
fileprivate var documentPath : String? = ""
fileprivate var uploadImageDirectoryPath : String? = ""
fileprivate var fileManager : FileManager?
fileprivate var updateUploadStatus : TaskFinishedEvent?
fileprivate var totalUploadedImage : Int = 0
fileprivate var totalImages : Int = 0
// MARK: - Lifecycle -
static let sharedInstance : ImageUploadManager = {
let instance = ImageUploadManager()
return instance
}()
deinit{
}
override init() {
super.init()
self.setupOnInit()
}
// MARK: - Public Interface -
open func addImageForUpload(arrImage : [UIImage]) -> Bool
{
if isUploadingRunning == false{
totalImages = totalImages + arrImage.count
self.saveImagesInCatch(arrImage: arrImage)
if self.updateUploadStatus != nil
{
self.updateUploadStatus!(true,NSArray(array: [totalUploadedImage , totalImages]))
}
self.prepareImageForUpload(imagePath: self.getImageForUploadOnServer())
}
return isUploadingRunning
}
open func setUpdateProgressStatusEven(event : @escaping TaskFinishedEvent){
updateUploadStatus = event
}
open func getTotalImageCount() -> Int
{
do
{
return try fileManager!.contentsOfDirectory(atPath: uploadImageDirectoryPath! as String).count
}
catch let error as NSError
{
print("Error while Getting Total Image Count:- \(error.localizedDescription)")
return 0
}
}
open func isUploadOperationRunning() -> Bool{
return isUploadingRunning
}
// MARK: - Internal Helpers -
fileprivate func setupOnInit()
{
documentPath = AppUtility.getDocumentDirectoryPath()
fileManager = FileManager()
uploadImageDirectoryPath = AppUtility.stringByPathComponet(fileName: "uploadImage", Path: documentPath!)
}
fileprivate func saveImagesInCatch(arrImage : [UIImage])
{
if !(fileManager?.fileExists(atPath: uploadImageDirectoryPath!))!
{
do
{
try fileManager?.createDirectory(atPath: uploadImageDirectoryPath!, withIntermediateDirectories: false, attributes: nil)
}
catch let error as NSError{
print("Error While Create Directory :- \(error.localizedDescription)")
return
}
}
var currentIndex : Int = totalUploadedImage
for image in arrImage
{
var imagePath : String? = AppUtility.stringByPathComponet(fileName: "\(currentIndex).jpg", Path: uploadImageDirectoryPath!)
print("imagePath:- \(imagePath)")
var img : UIImage? = UIImage .compressImage(image, compressRatio: 0.2, maxCompressRatio: 0.5)
var imageData : Data? = UIImageJPEGRepresentation(img!, 0.0)!
do{
try imageData! .write(to: URL(fileURLWithPath : imagePath!), options: Data.WritingOptions.atomic)
}
catch let error as NSError{
print("Error while saveing image : \(error.localizedDescription)")
}
currentIndex = currentIndex + 1
imagePath = nil
imageData = nil
img = nil
}
print("finish Save")
}
fileprivate func getImageForUploadOnServer() -> String
{
do
{
let tmpFileList : [String] = try fileManager!.contentsOfDirectory(atPath: uploadImageDirectoryPath! as String)
if tmpFileList.count > 0
{
return AppUtility.stringByPathComponet(fileName: tmpFileList.first!, Path: uploadImageDirectoryPath!)
}
}
catch let error as NSError
{
print("Error while Feting Image:- \(error.localizedDescription)")
}
return ""
}
fileprivate func prepareImageForUpload(imagePath : String)
{
if (fileManager?.fileExists(atPath: imagePath))!
{
var dicImgData : NSMutableDictionary? = NSMutableDictionary()
var imageData : NSData! = NSData(contentsOfFile: imagePath)!
dicImgData! .setObject(imageData, forKey: "data" as NSCopying)
dicImgData! .setObject("imagefile", forKey: "name" as NSCopying)
dicImgData! .setObject("imagefile", forKey: "fileName" as NSCopying)
dicImgData! .setObject("image/jpeg", forKey: "type" as NSCopying)
isUploadingRunning = true
self.uploadImageRequest(dicImage: dicImgData! , uploadFilePath: imagePath)
dicImgData = nil
imageData = nil
}
}
// MARK: - Server Helpers -
func uploadImageRequest(dicImage : NSDictionary , uploadFilePath : String)
{
var dicParameter : NSMutableDictionary! = NSMutableDictionary()
dicParameter .setValue("1", forKey: "status")
BaseAPICall.shared.uploadImage(url: APIConstant.uploadPhoto, Parameter: dicParameter, Images: [dicImage], Type: APITask.UploadAllImages) { [weak self] (result) in
if self == nil{
return
}
switch result{
case .Success( _, _):
self!.totalUploadedImage = self!.totalUploadedImage + 1
do
{
try self!.fileManager?.removeItem(atPath: uploadFilePath)
if self!.getTotalImageCount() > 0
{
if self!.updateUploadStatus != nil
{
self!.updateUploadStatus!(true,NSArray(array: [self!.totalUploadedImage , self!.totalImages]))
}
self!.prepareImageForUpload(imagePath: self!.getImageForUploadOnServer())
}
else
{
if self!.updateUploadStatus != nil
{
self!.updateUploadStatus!(true,NSArray(array: [self!.totalUploadedImage , self!.totalImages]))
}
self!.totalUploadedImage = 0
self!.totalImages = 0
self!.isUploadingRunning = false
}
}
catch let error as NSError{
print("Error While Remove image :- \(error.localizedDescription)")
}
break
case .Error(let error):
AppUtility.executeTaskInMainQueueWithCompletion {
AppUtility.showWhisperAlert(message: error!.serverMessage, duration: 1.0)
}
break
case .Internet( _):
break
}
}
dicParameter = nil
}
}
import UIKit
class MainResponse: NSObject
{
// MARK: - Attributes -
// MARK: - Lifecycle -
required override init() {
super.init()
}
// MARK: - Public Interface -
func getModelFromResponse(response : AnyObject , task : APITask) -> AnyObject
{
var returnModel : AnyObject = response
switch task
{
}
default:
break
}
return returnModel
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment