JKSDEV JKSDEV - 3 months ago 25
Swift Question

Trying to convert C-Style statement to Swift 3

I understand this question has been asked before and I have tried to understand the answers to apply to the code I am working with, for example both; Q1 & Q2

Previous Code with Error

let n = mutableRows.count
var i = 0, rows: [IndexPath] = []

for (i = 0; i < n; i += 1) {
rows.append(mutableRows[i] as! IndexPath)
}


My Update to Swift 3.0

for i in stride(from: 0, to: n, by: +1){
rows.append(mutableRows[i] as! IndexPath)
}


Even thought I don't get any errors the function does not work. Does anyone know how to correctly change the For statement to Swift 3.0 ?

Here's the full code;

func longPress(_ gesture: UILongPressGestureRecognizer) {
let location = gesture.location(in: self)
let indexPath = indexPathForRow(at: location)
let sections = numberOfSections
var rows = 0
for i in 0 ..< sections {
rows += numberOfRows(inSection: i)
}

// get out of here if the long press was not on a valid row or our table is empty
// or the dataSource tableView:canMoveRowAtIndexPath: doesn't allow moving the row
if (rows == 0 || (gesture.state == UIGestureRecognizerState.began && indexPath == nil) ||
(gesture.state == UIGestureRecognizerState.ended && currentLocationIndexPath == nil)) {
cancelGesture()
return
}

// started
if gesture.state == UIGestureRecognizerState.began {
isEnabled = false
let cell = cellForRow(at: indexPath!)!;
// draggingRowHeight = cell.frame.size.height;
cell.setSelected(false, animated: false)
cell.setHighlighted(false, animated: false)

// make an image from the pressed tableview cell
UIGraphicsBeginImageContextWithOptions(cell.bounds.size, false, 0)
cell.layer.render(in: UIGraphicsGetCurrentContext()!)
let cellImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

// create and image view that we will drag around the screen
if draggingView == nil {
draggingView = UIImageView(image: cellImage)
addSubview(draggingView!)
let rect = rectForRow(at: indexPath!)
draggingView!.frame = draggingView!.bounds.offsetBy(dx: rect.origin.x, dy: rect.origin.y)

// add drop shadow to image and lower opacity
draggingView!.layer.masksToBounds = false
draggingView!.layer.shadowColor = UIColor.black.cgColor
draggingView!.layer.shadowOffset = CGSize(width: 0, height: 0);
draggingView!.layer.shadowRadius = 4.0;
draggingView!.layer.shadowOpacity = 0.7;
draggingView!.layer.opacity = Float(draggingViewOpacity);

// zoom image towards user
UIView.beginAnimations("zoom", context: nil)
draggingView!.transform = CGAffineTransform(scaleX: 1.1, y: 1.1);
draggingView!.center = CGPoint(x: center.x, y: location.y);
UIView.commitAnimations()
}
cell.isHidden = true;
currentLocationIndexPath = indexPath;
initialIndexPath = indexPath;

// enable scrolling for cell
scrollDisplayLink = CADisplayLink(target: self, selector: #selector(SBGestureTableView.scrollTableWithCell(_:)))
scrollDisplayLink?.add(to: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
}
// dragging
else if gesture.state == UIGestureRecognizerState.changed {
var rect = bounds;
// adjust rect for content inset as we will use it below for calculating scroll zones
rect.size.height -= contentInset.top;
let location = gesture.location(in: self);
// tell us if we should scroll and which direction
let scrollZoneHeight = rect.size.height / 6;
let bottomScrollBeginning = contentOffset.y + contentInset.top + rect.size.height - scrollZoneHeight;
let topScrollBeginning = contentOffset.y + contentInset.top + scrollZoneHeight;
// we're in the bottom zone
if location.y >= bottomScrollBeginning {
scrollRate = Double((location.y - bottomScrollBeginning) / scrollZoneHeight);
}
// we're in the top zone
else if (location.y <= topScrollBeginning) {
scrollRate = Double((location.y - topScrollBeginning) / scrollZoneHeight);
}
else {
scrollRate = 0;
}
}
// dropped
else if gesture.state == UIGestureRecognizerState.ended {
isEnabled = true
let indexPath: IndexPath = currentLocationIndexPath!
let cell = cellForRow(at: indexPath)!
// remove scrolling CADisplayLink
scrollDisplayLink?.invalidate();
scrollDisplayLink = nil;
scrollRate = 0;

UIView.animate(withDuration: 0.3, animations: { () -> Void in
let rect = self.rectForRow(at: indexPath)
self.draggingView!.transform = CGAffineTransform.identity
self.draggingView!.frame = self.draggingView!.bounds.offsetBy(dx: rect.origin.x, dy: rect.origin.y)
}, completion: {(Bool) -> Void in
self.draggingView!.removeFromSuperview()
cell.isHidden = false
let visibleRows: NSArray = self.indexPathsForVisibleRows! as NSArray
let mutableRows = visibleRows.mutableCopy() as! NSMutableArray
mutableRows.remove(indexPath)

let n = mutableRows.count
var i = 0, rows: [IndexPath] = []


for (i = 0; i < n; i += 1) {
rows.append(mutableRows[i] as! IndexPath)
}


self.reloadRows(at: rows as [IndexPath], with: UITableViewRowAnimation.none)
self.currentLocationIndexPath = nil
self.draggingView = nil
})
}
}

Answer

You can simply do this:

for row in mutableRows {
    rows.append(row as! IndexPath)
}

The for...in loop is very useful. In every iteration, the value of row is changed to the next item in the mutableRowsArray. And the loop ends when all items in the array has been iterated.

This is even simpler!

rows = mutableRows.map { $0 as! IndexPath }