【问题标题】:Trying to convert C-Style statement to Swift 3 [closed]尝试将 C 样式语句转换为 Swift 3 [关闭]
【发布时间】:2016-09-06 18:54:26
【问题描述】:

我知道以前有人问过这个问题,并且我试图理解适用于我正在使用的代码的答案,例如两者; Q1 & Q2

以前的代码有错误

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

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

我对 Swift 3.0 的更新

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

即使我没有收到任何错误,该功能也不起作用。有谁知道如何正确地将 For 语句更改为 Swift 3.0 ?

这是完整的代码;

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
        })
    }
}

【问题讨论】:

  • 为什么不直接使用for row in mutableRows { rows.append(row) ...(从 Swift 1.0 开始提供)
  • PS: 为什么这个 ObjectiveC 风格的 mutableCopyNSMutableArray??学习使用 Swift 原生类型的好处,letvar 的区别以及它强大的类型系统。例如使用indexPathsForVisibleRows! as NSArray,您会丢弃类型信息并必须重新转换它。这效率很低。
  • @vadian 因为 row 实际上是类型 int 并且没有成员 append
  • 不,在提到的那一刻rows[IndexPath] -> 见var i = 0, rows: [IndexPath] = [] 这一行

标签: swift swift3


【解决方案1】:

你可以这样做:

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

for...in 循环非常有用。在每次迭代中,row 的值都会更改为mutableRowsArray 中的下一项。当数组中的所有项都被迭代后,循环结束。

这更简单!

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

【讨论】:

  • 我收到了错误 Value of type 'Int' has no member 'append' for rows.append 这是因为它不是一个数组。 var rows = 0 for i in 0 ..&lt; sections { rows += numberOfRows(inSection: i) }
  • 您使用了两次rows(分别为Int[IndexPath])。这是模棱两可和令人困惑的。
  • 显然你有两个rows 变量。如果你还不能说,那会很混乱。更改其中之一的名称。 @JKSDEV
  • @Sweeper 是的,抱歉,只需重新阅读代码并修复命名即可。谢谢 !!抱歉,我的老板向我强调要在明天之前将其转换为 Swift 3
【解决方案2】:

可以直接追加数组:

let visibleRows = (self.indexPathsForVisibleRows ?? [])
    .filter { $0 != indexPath }

rows.append(contentsOf: visibleRows)

在 Swift 中无需使用NSMutableArray

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2018-01-22
    • 1970-01-01
    相关资源
    最近更新 更多