Last active
August 20, 2017 07:58
-
-
Save mspvirajpatel/ad8aee9821fe61d94925c438ef712f2c to your computer and use it in GitHub Desktop.
Image Upload Manager with Almofire and Create With Model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 - | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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...") | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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