upload collection view images into server using swift - swift2

I'm developing an app which has UICollectionView as like #zhangao0086/DKImagePickerController# example in Github. Now i need to upload the displayed UICollectionviewCell images into server. Can any one suggest me the right tuts for uploading. Thanks in advance.
UICollectionView code as follows:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let asset = self.assets![indexPath.row]
var cell: UICollectionViewCell?
var imageView: UIImageView?
if asset.isVideo {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellVideo", forIndexPath: indexPath)
imageView = cell?.contentView.viewWithTag(1) as? UIImageView
} else {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellImage", forIndexPath: indexPath)
imageView = cell?.contentView.viewWithTag(1) as? UIImageView
}
if let cell = cell, imageView = imageView {
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
let tag = indexPath.row + 1
cell.tag = tag
asset.fetchImageWithSize(layout.itemSize.toPixel(), completeBlock: { image, info in
if cell.tag == tag {
imageView.image = image
}
})
}
return cell!
}
uploading the image into server
func barButtonItemClicked(barButtonItem: UIBarButtonItem)
{
let myUrl = NSURL(string: "http://moneymonkey.tokiiyo.com/api/signature");
let typeItem: InsuranceType = InsuranceManager.sharedInstance.TypeArray[0]
let compItem: Companies = InsuranceManager.sharedInstance.CompArray[0]
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let param = [
"api_key" : "AiK58j67",
"api_secret" : "a#9rJkmbOea90-",
"phone" : "\(mobile)",
"policy_type" : "\(typeItem.name)",
"company" : "\(compItem.cname)"
]
print("Policy_type: \(typeItem.name)")
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImagePNGRepresentation(?) //here what imageView
if(imageData==nil) { return; }
request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
// You can print out response object
print("******* response = \(response)")
// Print out reponse body
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("****** response data = \(responseString!)")
do{
_ = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
dispatch_async(dispatch_get_main_queue(),{
});
}
catch
{
// report error
print("Oops!! Something went wrong\(error)")
}
}
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "image.png"
let mimetype = "image/png"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}

J
you can use Alamofire https://github.com/Alamofire/Alamofire
Use like this :
Alamofire.upload(.POST, "YourURl", file: YourFile)
.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
print(totalBytesWritten)
// This closure is NOT called on the main queue for performance
// reasons. To update your ui, dispatch to the main queue.
dispatch_async(dispatch_get_main_queue()) {
print("Total bytes written on main queue: \(totalBytesWritten)")
}
}
.responseJSON { response in
debugPrint(response)
}

Related

Swift 3: UICollectionView download video snapshot. UI is freezed while trying to download snapshot

I'm trying to download video preview base on remote video URL. In my project, the server cannot return snapshot image of the videos, that's why I have to do it manually.
In table view, I have code like this in cellForItemAt to get video preview
DataManager.sharedInstance.getCachedImage(url: movie.url!, handler: { (image) in
cell.ivCover.image = image
})
and my getCachedImage function in DataManager:
func getCachedImage(url: String, handler: #escaping(_ result:UIImage) -> Void){
DispatchQueue.global().async {
let userDefaults = UserDefaults.standard
if let imageData = userDefaults.object(forKey: url){
if let finalImg = UIImage(data: imageData as! Data){
DispatchQueue.main.async {
handler(finalImg)
}
print("USING CACHED IMG")
}else{
DispatchQueue.main.async {
handler(#imageLiteral(resourceName: "cover"))
}
print("Cannot parse cached data to image. Use default")
}
}else{
let asset = AVURLAsset(url: URL(string: url)!)
let generate = AVAssetImageGenerator(asset: asset)
generate.appliesPreferredTrackTransform = true
var thumbTime = asset.duration
thumbTime.value = 1
var imgRef:CGImage?
do{
print("Downloading thum from url: \(url)")
imgRef = try generate.copyCGImage(at: thumbTime, actualTime: nil)
}catch let error{
print("Error download thum: \(error.localizedDescription)")
}
var finalImg:UIImage
if let _ = imgRef{
finalImg = UIImage(cgImage: imgRef!)
userDefaults.set(UIImagePNGRepresentation(finalImg), forKey: url)
}else{
finalImg = #imageLiteral(resourceName: "cover")
print("Download thumnail failed. Use default")
}
DispatchQueue.main.async {
handler(finalImg)
}
}
}
}
The problem is that, sometimes I scroll the Collection view, UI is freezed, sometimes it's not. Please note that this video is on REMOTE SERVER, NOT local video.
I've spent days to figure out the issue but still not able to find out what went wrong. Please help!
Or is there any existing library I can use?
import UIKit
import Photos
class ImportViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func myButton(_ sender: Any) {
let videoURL = "https://youerdomin.com/file.mp4"
print("1")
DispatchQueue.global(qos: .background).async {
print("2")
if let url = URL(string: videoURL), let urlData = NSData(contentsOf: url) {
print("3")
let documentsPath =
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/tempFile.mp4"
DispatchQueue.main.async {
print("4")
urlData.write(toFile: filePath, atomically: true)
PHPhotoLibrary.shared().performChanges({
print("5")
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
}) { completed, error in
print("6")
if completed {
print("Video is saved!")
}else{
print("7: ",filePath)
}
}
}
}else{
print("8")
}
}
}
}

Best way to load image url swift 2 in UITableView

I want to create A Ui TableView with a list of image link with swift 2:
for example : var images = ["link1","link2",...,linkN"]
I create a custom cell to display the image :
let cell = tableView.dequeueReusableCellWithIdentifier(CurrentFormTableView.CellIdentifiers.ImageCell, forIndexPath: indexPath) as! ImageCell
cell.urlImageView.tag = indexPath.row
cell.displayImage(images[index.row])
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
And here I have my custom cell to load my image :
import UIKit
class ImageCell: UITableViewCell {
#IBOutlet weak var urlImageView: UIImageView!
#IBOutlet weak var loadingStatus: UIActivityIndicatorView!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func loadImageFromUrl(url: String, view: UIImageView){
if view.image == nil {
self.startLoading()
// Create Url from string
let url = NSURL(string: url)!
// Download task:
// - sharedSession = global NSURLCache, NSHTTPCookieStorage and NSURLCredentialStorage objects.
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
// if responseData is not null...
if let data = responseData{
// execute in UI thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.stopLoading()
view.image = UIImage(data: data)
})
}
}
// Run task
task.resume()
}
}
func displayImage(imageUrl: String){
imageView?.image = nil
if imageUrl != nil && imageUrl != "" {
print(imageUrl)
loadImageFromUrl(imageUrl,view: urlImageView)
} else {
loadingStatus.hidden = true
}
}
func startLoading(){
loadingStatus.hidden = false
loadingStatus.startAnimating()
}
func stopLoading(){
loadingStatus.hidden = true
loadingStatus.stopAnimating()
}
}
The problem is that, she times the images are loading correctly, and sometimes, one image or more "override the other" so I have multiple identical images instead of see all my different images. How it is possible ? Where is my mistake ?
You're not implementing the reuse of the cells, meaning that the imageView's image of one cell will be the same as another that it was reused from, until the new image has loaded.
To prevent this, implement the -prepareForReuse: method:
override func prepareForReuse() {
super.prepareForReuse()
urlImageView.image = nil
// cancel loading
}
Furthermore, you shouldn't be doing any network-related code in the view layer, it should be done in the view controller. This will allow you to implement caching mechanisms if the image has already been downloaded for a specific cell, as well as alter the state of other views.
i.e. In your view controller:
var cachedImages = [String: UIImage]()
func cellForRow...() {
let imageURL = imageURLs[indexPath.row]
if let image = cachedImages[imageURL] {
cell.urlImageView.image = cachedImages[imageURL]
}
else {
downloadImage(indexPath, { image in
if let image = image {
cachedImages[imageURL] = image
cell.urlImageView.image = image
}
})
}
}
func downloadImage(indexPath: NSIndexPath, callback: () -> (UIImage?)) {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
// if responseData is not null...
if let data = responseData {
// execute in UI thread
dispatch_async(dispatch_get_main_queue(), {
callback(UIImage(data: data))
})
}
else {
dispatch_async(dispatch_get_main_queue(), {
callback(nil)
})
}
}
// Run task
task.resume()
}

Asynchronously Downloading The Image From Parse

I'm trying to download images from parse via 'Asynchronously'.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil) [0] as? CatsTableViewCell
}
if let pfObject = object {
cell?.catNameLabel?.text = pfObject["name"] as? String
var votes:Int? = pfObject["votes"] as? Int
if votes == nil {
votes = 0
}
cell?.catVotesLabel?.text = "\(votes!) votes"
var credit:String? = pfObject["cc_by"] as? String
if credit != nil {
cell?.catCreditLabel?.text = "\(credit!) / CC 2.0"
}
cell?.catImageView?.image = nil
if var urlString:String? = pfObject["url"] as? String {
var url:NSURL? = NSURL(string: urlString!)
if var url:NSURL? = NSURL(string: urlString!) {
var error:NSError?
var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)
NSOperationQueue.mainQueue().cancelAllOperations()
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
(response:NSURLResponse?, imageData:NSData?, error:NSError?) -> Void in
cell?.catImageView?.image = UIImage(data: imageData!)
})
}
}
now I changed few code
completionHandler: {
(response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in
cell?.catImageView?.image = UIImage(data: imageData)
to
completionHandler: {
(response:NSURLResponse?, imageData:NSData?, error:NSError?) -> Void in
cell?.catImageView?.image = UIImage(data: imageData!)
and no critical errors but the image doesn't show up on the simulator.
Any help would be appreciate. Thank you all.
-first problem-
*And the problem is occurred down below
cell?.catImageView?.image = UIImage(data: imageData)
it says
Value of optional type ‘()?’ not unwrapped; did you mean to use ‘!’ or ‘?’?*
The initializer init(data:) returns an optional UIImage. You should check and unwrap it:
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
(response: NSURLResponse?, imageData: NSData?, error: NSError?) -> Void in
if let e = error {
print(e)
return
}
guard let data = imageData else { return }
if let image = UIImage(data: data) {
cell?.catImageView?.image = image
}
})

swift: refresh/reload table view did not work

i'm new in swift development, i added data in server tried to refresh tableviewcontroller with refreshcontrol function but value in table view didn't change.
class MainTableViewController: UITableViewController, UINavigationControllerDelegate {
#IBOutlet var sosTableView: UITableView!
var datas = [dataSos]()
override func viewDidLoad() {
super.viewDidLoad()
let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
spinningActivity.labelText = "Loading"
spinningActivity.detailsLabelText = "Please wait"
dispatch_async(dispatch_get_main_queue()) {
self.loadDataServer()
spinningActivity.hide(true)
self.sosTableView.reloadData()
}
//loadDataSos()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
var refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: Selector("refreshData"), forControlEvents: UIControlEvents.ValueChanged)
self.refreshControl = refreshControl
}
Refresh func
func refreshData(){
dispatch_async(dispatch_get_main_queue()) {
self.loadDataServer()
self.sosTableView.reloadData()
}
refreshControl?.endRefreshing()
}
load server func
func loadDataServer(){
do {
let data = NSData(contentsOfURL: NSURL(string: "http://xxxx/scripts/xxx.php")!)
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
//let NumberOfPersons = jsonResult.count
// **LOOP THROUGH THE JSON ARRAY**
for anItem in jsonResult as! [Dictionary<String, AnyObject>] {
let userId = anItem["userId"] as! String
let userName = anItem["firstName"] as! String
let userAddress = anItem["address"] as! String
let userDate = anItem["date"] as! String
let userLocation = anItem["location"] as! String
var userEvent = anItem["event"] as? String
let sosId = anItem["sosId"] as! String
// do something with personName and personID
let imageUrl = NSURL(string:"http://xxx")
let imageData = NSData(contentsOfURL: imageUrl!)
if userEvent == nil{
userEvent = "Need Help"
}else if userEvent! == "1" {
userEvent! = "Thief"
}
else if userEvent! == "2" {
userEvent! = "Fire"
}
else{
userEvent! = "Healthy Issue"
}
//print(personName)
if imageData == nil{
let photo1 = UIImage(named: "defaultPhoto")!
let data1 = dataSos(userId: userId, name: userName, location: userLocation, address: userAddress, event: userEvent!, date: userDate, photo: photo1, sosId: sosId)
self.datas += [data1]
}
else{
let photo1 = UIImage(data: imageData!)
//let photo1 = UIImage(named: "defaultPhoto")
let data1 = dataSos(userId: userId, name: userName, location: userLocation, address: userAddress, event: userEvent!, date: userDate, photo: photo1, sosId: sosId)
self.datas += [data1]
}
}
} catch let error as NSError {
print(error)
}
// }
}
Update: table view data source
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// warning Incomplete implementation, return the number of rows
return datas.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MainTableViewCell
// Configure the cell...
let data0 = datas[indexPath.row]
cell.nameLabel.text = data0.name
cell.locationLabel.text = data0.location
cell.addressTextView.text = data0.address
cell.eventLabel.text = data0.event
cell.dateLabel.text = data0.date
cell.photoLabel.image = data0.photo
self.roundingUIView(cell.photoLabel, cornerRadiusParam: 35)
return cell
}
Ok, I just understood that you're inheriting for UITableViewController, therefor you already have tableView property inherited from it. The table view from this property has already set delegate and dataSource to your controller, but not for your custom sosTableView. You should replace your custom sosTableView with inherited tableView property and then everything gonna work as you're expecting.

PFQueryTableView Controller not loading custom Cells

Im working on an app and I would like it to populate the cells based on users who are within a set distance from the currentuser. For some reason the customcells are not being populated with the correct objects. The labels and images that are supposed to be retrieved are blank. All i get is a blank cell. I made sure i gave the cell identifier the correct name, and i also made sure to link the tableviewcontroller and the tablecellview to their respective classes,but still no luck.
first i created initializers:
class TableViewController: PFQueryTableViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var currLocation: CLLocationCoordinate2D?
override init!(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "User"
self.textKey = "FBName"
// self.imageKey = "pictureURL"
self.pullToRefreshEnabled = true
self.objectsPerPage = 10
self.paginationEnabled = true
}
Then in viewDidLoad i enabled location services:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 200
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
loadData()
println("location services enabled bruh")
}
}
Next i overrode the queryfortable function:
override func queryForTable() -> PFQuery! {
let query = PFQuery(className: "User")
if let queryLoc = currLocation {
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: queryLoc.latitude, longitude: queryLoc.longitude), withinMiles: 50)
query.limit = 40
query.orderByAscending("createdAt")
println("\(queryLoc.latitude)")
return query
} else {
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: 37.411822, longitude: -121.941125), withinMiles: 50)
query.limit = 40
query.orderByAscending("createdAt")
println("else statement")
return query
}
}
then the objectAtIndexPath function
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject! {
var obj : PFObject? = nil
if indexPath.row < self.objects.count {
obj = self.objects[indexPath.row] as? PFObject
}
return obj
}
and lastly I returned the cell, but for some reason it does not work:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject?) -> PFTableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as TableViewCell
cell.userName?.text = object?.valueForKey("FBName") as? String
let userProfilePhotoURLString = object?.valueForKey("pictureURL") as? String
var pictureURL: NSURL = NSURL(string: userProfilePhotoURLString!)!
var urlRequest: NSURLRequest = NSURLRequest(URL: pictureURL)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (NSURLResponse response, NSData data,NSError error) -> Void in
if error == nil && data != nil {
cell.userImage?.image = UIImage(data: data)
}
}
cell.ratingsView?.show(rating: 4.0, text: nil)
return cell
}
ps, i have the number of sections set to 1, just didnt think that method would be useful to show here.
okay I found the issue! The issue was that I was trying to use PFQuery in order to retrieve a list of PFUsers. I found out that cannot be done using PFQuery infact PFUser has it's own query method for retrieving information from its users.
all i had to do was replace this line:
let query = PFQuery(className: "User")
with this:
let query = PFUser.query()

Resources