草庐IT

ios - 当我在那个 swift ios 上绘制时,ImageView 会改变坐标

coder 2024-01-22 原文

我正在关注 this tutorial ,首先当应用程序启动时一切正常 imagView 设置在我设置的位置。但问题是,当我开始在 imageView 上绘制时,imageView 的大小会调整为不明确的坐标,并且它会扩大并占用太多空间导致不明确的 View ,即使我已经设置了自动布局。 可能是我遗漏了什么,这里是代码:

import UIKit
import CoreImage

class ViewController: UIViewController {

let imageNameIs = "BradPitImage"
var lastPoint = CGPoint.zero
var red: CGFloat = 0.0
var green: CGFloat = 0.0
var blue: CGFloat = 0.0
var brushWidth: CGFloat = 10.0
var opacity: CGFloat = 1.0
var swiped = false

@IBOutlet weak var tempImageView: UIImageView!
var tempImageViewtemp : UIImageView = UIImageView()

@IBOutlet weak var resetButton: UIButton!
@IBOutlet weak var saveButton: UIButton!

@IBAction func resetAct(_ sender: Any) {
    tempImageView.image = nil
    tempImageView.image = UIImage(named: imageNameIs)
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.tempImageView.image = UIImage(named: imageNameIs)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    swiped = false
    if let touch = touches.first {
        lastPoint = touch.location(in: self.tempImageView)//view)
    }
}

func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
    // 1
    UIGraphicsBeginImageContext(view.frame.size)//(tempImageView.frame.size) makes lines coluored of image
    let context = UIGraphicsGetCurrentContext()
    tempImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height))

    // 3
    context!.move(to: fromPoint)
    context!.addLine(to: toPoint)
    context!.setLineCap(.round)
    context!.setLineWidth(brushWidth)
    context!.setStrokeColor(red: red, green: green, blue: blue, alpha: 1)
    context!.setBlendMode(.normal)

    // 4
    context!.strokePath()
    //CGContextStrokePath(context!)

    // 5
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    tempImageView.alpha = opacity
    UIGraphicsEndImageContext()
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    swiped = true
    if let touch = touches.first {
        let currentPoint = touch.location(in: view)
        drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)
    // 7
    lastPoint = currentPoint
    }
}

 func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
    // 6
    swiped = true
    if let touch = touches.first as? UITouch {
        let currentPoint = touch.location(in: view)
        drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)
        // 7
        lastPoint = currentPoint
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if !swiped {
        //draw a single point
        drawLineFrom(fromPoint: lastPoint, toPoint: lastPoint)
    }
    UIGraphicsBeginImageContext(tempImageViewtemp.frame.size)
    tempImageViewtemp.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: 1)
    tempImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: opacity)
    tempImageViewtemp.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
  }
}

图片如下:

1) 何时启动

2)当我开始画画的时候

**根据DonMag的回答更新坐标仍然不明确**

它仅适用于纵向,问题是当我使用横向模式并开始绘图时,图像尺寸缩小到顶部并且底部越来越宽,然后我使用纵向模式然后图像从顶部变为中心底部越窄,我根据您的代码添加了新的屏幕截图

1) 第一次从纵向到横向:

2) 当我开始绘图时,它缩小了图像并且绘图变得模糊

现在从横向启动时看起来像这样并且绘图不会减少也不会产生任何模糊:

但是当转向肖像图像时会像这样缩小

最佳答案

一些事情...

  1. 您似乎已将 ImageView 设置为 Aspect Fit scale。这意味着您的图像与 ImageView 本身的大小不同。

  2. 您混合了 ImageView 和 Root View 的帧大小。

这是您的代码,稍作修改。查看 //--- 指示的注释。您应该能够替换当前代码并按原样运行它:

import UIKit
import CoreImage

extension UIView {
    // return content of view as a UIImage
    // can be used to get a copy of the rendered image view
    // e.g. the result of scaling setting

    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }

}

class ViewController: UIViewController {

    let imageNameIs = "BradPitImage"
    var lastPoint = CGPoint.zero
    var red: CGFloat = 0.0
    var green: CGFloat = 0.0
    var blue: CGFloat = 0.0
    var brushWidth: CGFloat = 10.0
    var opacity: CGFloat = 1.0
    var swiped = false

    @IBOutlet weak var tempImageView: UIImageView!
    var tempImageViewtemp : UIImageView = UIImageView()

    // ---
    // --- this will hold a copy of the resized image (for reset)
    var resizedImage: UIImage!

    @IBOutlet weak var resetButton: UIButton!
    @IBOutlet weak var saveButton: UIButton!

    @IBAction func resetAct(_ sender: Any) {
        // ---
        // --- reset using the resized image from viewDidAppear
        tempImageView.image = resizedImage
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tempImageView.image = UIImage(named: imageNameIs)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // ---
        // --- create a resized copy of the original image
        // --- (handles aspect fit scale)
        resizedImage = tempImageView.asImage()
        tempImageView.image = resizedImage

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        swiped = false
        if let touch = touches.first {
            // ---
            // --- get point ** in tempImageView **
            lastPoint = touch.location(in: self.tempImageView)  //view)
        }
    }

    func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
        // 1

        // ---
        // --- get the bounds of tempImageView
        let rect = tempImageView.bounds

        // ---
        // --- use the bounds for the image context size
        UIGraphicsBeginImageContext(rect.size)

        let context = UIGraphicsGetCurrentContext()

        // ---
        // --- draw the image into the bounds rect
        tempImageView.image?.draw(in: rect)

        // 3
        context!.move(to: fromPoint)
        context!.addLine(to: toPoint)
        context!.setLineCap(.round)
        context!.setLineWidth(brushWidth)
        context!.setStrokeColor(red: red, green: green, blue: blue, alpha: 1)
        context!.setBlendMode(.normal)

        // 4
        context!.strokePath()
        //CGContextStrokePath(context!)

        // 5
        tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        tempImageView.alpha = opacity
        UIGraphicsEndImageContext()
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        swiped = true
        if let touch = touches.first {

            // ---
            // --- get point ** in tempImageView **
            let currentPoint = touch.location(in: self.tempImageView)

            drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)

            // 7
            lastPoint = currentPoint
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !swiped {
            //draw a single point
            drawLineFrom(fromPoint: lastPoint, toPoint: lastPoint)
        }

        // ---
        // don't know what you're doing with tempImageViewtemp,
        // but you probably want to change the sizing here to match elsewhere
        UIGraphicsBeginImageContext(tempImageViewtemp.frame.size)
        tempImageViewtemp.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: 1)
        tempImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: opacity)
        tempImageViewtemp.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    }
}

编辑:

这里有一种略有不同的方法,可以让您在自己的道路上走得更远。

不是更改图像,而是更改 imageView 的大小以匹配图像的比例。

Storyboard布局:

ImageView 在白色父 View 中保持居中的约束,并且将限制其宽度和高度,保持比例(纵横比)。

白色 View 有限制,以保持其大小/位于按钮上方。

结果 - 纵向,左眼画了一个圆圈:

结果 - 设备旋转到横向,右眼周围画了另一个圆圈:

您还会在代码/注释中注意到“brushWidth”必须根据图像高度进行调整...仅使用 10 磅,因为当图像较短时宽度会导致“较粗”的线条(景观)。

代码如下:

//
//  DrawOnViewController.swift
//
//  Created by Don Mag on 11/7/18.
//

import UIKit

extension NSLayoutConstraint {
    /**
    Change multiplier constraint

    - parameter multiplier: CGFloat
    - returns: NSLayoutConstraint
    */
    func setMultiplier(multiplier:CGFloat) -> NSLayoutConstraint {

        NSLayoutConstraint.deactivate([self])

        let newConstraint = NSLayoutConstraint(
            item: firstItem as Any,
            attribute: firstAttribute,
            relatedBy: relation,
            toItem: secondItem,
            attribute: secondAttribute,
            multiplier: multiplier,
            constant: constant)

        newConstraint.priority = priority
        newConstraint.shouldBeArchived = self.shouldBeArchived
        newConstraint.identifier = self.identifier

        NSLayoutConstraint.activate([newConstraint])
        return newConstraint
    }
}

class DrawOnViewController: UIViewController {

    let imageNameIs = "BradPitImage"
    var lastPoint = CGPoint.zero
    var red: CGFloat = 0.0
    var green: CGFloat = 0.0
    var blue: CGFloat = 0.0
    var brushWidth: CGFloat = 10.0
    var opacity: CGFloat = 1.0
    var swiped = false

    @IBOutlet weak var tempImageView: UIImageView!
    var tempImageViewtemp : UIImageView = UIImageView()

    // ---
    // --- this will hold a reference to the image view's aspect ratio constraint
    @IBOutlet var imageViewAspectRatioConstraint: NSLayoutConstraint!

    // ---
    // --- this will be used to allow "brushWidth" to remain
    // --- constant when device is rotated
    var loadedImageHeight: CGFloat = 0.0

    // ---
    // --- this will be the "brushWidth" relative to
    // --- to the image's originial height
    var adjustedBrushWidth: CGFloat = 0.0

    @IBOutlet weak var resetButton: UIButton!
    @IBOutlet weak var saveButton: UIButton!

    @IBAction func resetAct(_ sender: Any) {
        if let img = UIImage(named: imageNameIs) {
            // ---
            // --- reset the imageView's image
            tempImageView.image = img
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if let img = UIImage(named: imageNameIs) {

            let imgSize = img.size

            // ---
            // --- calculate the aspect ratio of the image
            let ratio = imgSize.width / imgSize.height

            // ---
            // --- change the image view's aspect ratio to match the image
            imageViewAspectRatioConstraint = imageViewAspectRatioConstraint.setMultiplier(multiplier: ratio)

            // ---
            // --- save original image height for brushWidth adjustment
            loadedImageHeight = imgSize.height

            // ---
            // --- set the imageView's image
            self.tempImageView.image = img

        }

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // ---
        // --- calculate brushWidth relative to image height scaled to image view height
        adjustedBrushWidth = brushWidth * loadedImageHeight / tempImageView.frame.height
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        swiped = false
        if let touch = touches.first {
            // ---
            // --- get point ** in tempImageView **
            lastPoint = touch.location(in: self.tempImageView)
        }
    }

    func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
        // 1

        // ---
        // --- get the bounds of tempImageView
        let rect = tempImageView.bounds

        // ---
        // --- use the bounds for the image context size
        UIGraphicsBeginImageContext(rect.size)

        let context = UIGraphicsGetCurrentContext()

        // ---
        // --- draw the image into the bounds rect
        tempImageView.image?.draw(in: rect)

        // 3
        context!.move(to: fromPoint)
        context!.addLine(to: toPoint)
        context!.setLineCap(.round)

        // ---
        // --- set line width proportional to current imageView height
        // --- use adjustedBrushWidth set in viewDidAppear
//      context!.setLineWidth(brushWidth * rect.height / loadedImageHeight)
        context!.setLineWidth(adjustedBrushWidth * rect.height / loadedImageHeight)

        context!.setStrokeColor(red: red, green: green, blue: blue, alpha: 1)
        context!.setBlendMode(.normal)

        // 4
        context!.strokePath()
        //CGContextStrokePath(context!)

        // 5
        tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
        tempImageView.alpha = opacity
        UIGraphicsEndImageContext()
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        swiped = true
        if let touch = touches.first {

            // ---
            // --- get point ** in tempImageView **
            let currentPoint = touch.location(in: self.tempImageView)

            drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)

            // 7
            lastPoint = currentPoint
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !swiped {
            //draw a single point
            drawLineFrom(fromPoint: lastPoint, toPoint: lastPoint)
        }

        // ---
        // don't know what you're doing with tempImageViewtemp,
        // but you probably want to change the sizing here to match elsewhere
        //      UIGraphicsBeginImageContext(tempImageViewtemp.frame.size)
        //      tempImageViewtemp.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: 1)
        //      tempImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: opacity)
        //      tempImageViewtemp.image = UIGraphicsGetImageFromCurrentImageContext()
        //      UIGraphicsEndImageContext()
    }
}

这是具有所需约束的 Storyboard:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bvb-cu-Gcn">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
        <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Draw On View Controller-->
        <scene sceneID="b4T-Zn-uEk">
            <objects>
                <viewController id="bvb-cu-Gcn" customClass="DrawOnViewController" customModule="SW4Temp" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="fif-yb-Cf8">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GU5-HP-5fd">
                                <rect key="frame" x="8" y="28" width="359" height="593"/>
                                <subviews>
                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="1MQ-UT-8dQ">
                                        <rect key="frame" x="0.5" y="117.5" width="358.5" height="358.5"/>
                                        <color key="backgroundColor" red="1" green="0.1857388616" blue="0.57339501380000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="width" secondItem="1MQ-UT-8dQ" secondAttribute="height" multiplier="1:1" id="xD6-8c-1AI"/>
                                        </constraints>
                                    </imageView>
                                </subviews>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstItem="1MQ-UT-8dQ" firstAttribute="height" secondItem="GU5-HP-5fd" secondAttribute="height" priority="750" id="14p-DB-cE1"/>
                                    <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="1MQ-UT-8dQ" secondAttribute="bottom" id="9A8-ey-EzV"/>
                                    <constraint firstItem="1MQ-UT-8dQ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="GU5-HP-5fd" secondAttribute="leading" id="DbB-Mv-lEx"/>
                                    <constraint firstItem="1MQ-UT-8dQ" firstAttribute="top" relation="greaterThanOrEqual" secondItem="GU5-HP-5fd" secondAttribute="top" id="Eq0-pn-RKN"/>
                                    <constraint firstItem="1MQ-UT-8dQ" firstAttribute="centerY" secondItem="GU5-HP-5fd" secondAttribute="centerY" id="d9A-Un-06B"/>
                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="1MQ-UT-8dQ" secondAttribute="trailing" id="dDp-HC-4pn"/>
                                    <constraint firstItem="1MQ-UT-8dQ" firstAttribute="centerX" secondItem="GU5-HP-5fd" secondAttribute="centerX" id="mqJ-4L-wQR"/>
                                </constraints>
                            </view>
                            <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QmC-N4-hsp">
                                <rect key="frame" x="20" y="629" width="39" height="30"/>
                                <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <state key="normal" title="Reset"/>
                                <connections>
                                    <action selector="resetAct:" destination="bvb-cu-Gcn" eventType="touchUpInside" id="5ug-cY-v6A"/>
                                </connections>
                            </button>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BWU-rw-ePF">
                                <rect key="frame" x="321" y="629" width="34" height="30"/>
                                <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <state key="normal" title="Save"/>
                                <connections>
                                    <action selector="resetAct:" destination="bvb-cu-Gcn" eventType="touchUpInside" id="JkQ-M7-brY"/>
                                </connections>
                            </button>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sia-an-mGC">
                                <rect key="frame" x="168.5" y="629" width="37" height="30"/>
                                <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <state key="normal" title="Color"/>
                            </button>
                        </subviews>
                        <color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="mdN-5j-gOT" firstAttribute="bottom" secondItem="sia-an-mGC" secondAttribute="bottom" constant="8" id="33Q-9r-cik"/>
                            <constraint firstItem="mdN-5j-gOT" firstAttribute="bottom" secondItem="BWU-rw-ePF" secondAttribute="bottom" constant="8" id="9Xw-wi-cSH"/>
                            <constraint firstItem="mdN-5j-gOT" firstAttribute="trailing" secondItem="BWU-rw-ePF" secondAttribute="trailing" constant="20" id="Bwp-Uu-Qt7"/>
                            <constraint firstItem="GU5-HP-5fd" firstAttribute="top" secondItem="mdN-5j-gOT" secondAttribute="top" constant="8" id="E63-DW-lHC"/>
                            <constraint firstItem="mdN-5j-gOT" firstAttribute="trailing" secondItem="GU5-HP-5fd" secondAttribute="trailing" constant="8" id="GDF-yb-Zhr"/>
                            <constraint firstItem="GU5-HP-5fd" firstAttribute="leading" secondItem="mdN-5j-gOT" secondAttribute="leading" constant="8" id="Pw9-SO-lkd"/>
                            <constraint firstItem="mdN-5j-gOT" firstAttribute="bottom" secondItem="QmC-N4-hsp" secondAttribute="bottom" constant="8" id="TKU-Ht-CmQ"/>
                            <constraint firstItem="QmC-N4-hsp" firstAttribute="leading" secondItem="mdN-5j-gOT" secondAttribute="leading" constant="20" id="Uwc-k4-TP4"/>
                            <constraint firstItem="QmC-N4-hsp" firstAttribute="top" secondItem="GU5-HP-5fd" secondAttribute="bottom" constant="8" id="ute-8t-Q2P"/>
                            <constraint firstItem="sia-an-mGC" firstAttribute="centerX" secondItem="fif-yb-Cf8" secondAttribute="centerX" id="zXd-nm-Goa"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="mdN-5j-gOT"/>
                    </view>
                    <connections>
                        <outlet property="imageViewAspectRatioConstraint" destination="xD6-8c-1AI" id="KWT-aA-gtN"/>
                        <outlet property="tempImageView" destination="1MQ-UT-8dQ" id="brX-iu-UgX"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="zoz-eV-W9h" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="48.799999999999997" y="624.73763118440786"/>
        </scene>
    </scenes>
</document>

关于ios - 当我在那个 swift ios 上绘制时,ImageView 会改变坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53169386/

有关ios - 当我在那个 swift ios 上绘制时,ImageView 会改变坐标的更多相关文章

  1. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  2. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  3. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  4. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

  5. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  6. ruby - 为 IO::popen 拯救 "command not found" - 2

    当我将IO::popen与不存在的命令一起使用时,我在屏幕上打印了一条错误消息:irb>IO.popen"fakefake"#=>#irb>(irb):1:commandnotfound:fakefake有什么方法可以捕获此错误,以便我可以在脚本中进行检查? 最佳答案 是:升级到ruby​​1.9。如果您在1.9中运行它,则会引发Errno::ENOENT,您将能够拯救它。(编辑)这是在1.8中的一种hackish方式:error=IO.pipe$stderr.reopenerror[1]pipe=IO.popen'qwe'#

  7. ruby - 我在哪里可以找到与其兼容的 Ruby 版本的 gems 版本号? - 2

    这个问题说明了一切。例如,我有一台安装了ruby​​1.8.6的服务器。当我尝试sudogeminstallroo时,它给出了错误nokogirirequiresRubyversion>=1.8.7。所以,我想安装与Ruby1.8.6兼容的旧版本roo。但我不知道去哪里搜索。我知道RubyForge,但它也没有说明Ruby的兼容版本。 最佳答案 蛮力方法是获取一个git克隆,搜索它指定的Ruby版本的位置,然后使用gitblame甚至gitpickaxe来确定最后一个没有的版本'没有那个要求。

  8. ruby - IO::EAGAINWaitReadable:资源暂时不可用 - 读取会阻塞 - 2

    当我尝试使用“套接字”库中的方法“read_nonblock”时出现以下错误IO::EAGAINWaitReadable:Resourcetemporarilyunavailable-readwouldblock但是当我通过终端上的IRB尝试时它工作正常如何让它读取缓冲区? 最佳答案 IgetthefollowingerrorwhenItrytousethemethod"read_nonblock"fromthe"socket"library当缓冲区中的数据未准备好时,这是预期的行为。由于异常IO::EAGAINWaitReadab

  9. ruby - Watir 无法找到我在 Chrome 的 DOM 检查器中看到的元素 - 2

    这是一个研究案例:......我正在尝试使用WatirRuby的API引用名为“bar”的嵌入元素。该元素由Chrome的DOM检查器显示,但我无法使用Watir的任何查找方法找到它:browser.embeds()#onlyisfoundbrowser.html.include?'bar'#=>false为什么会这样?为什么Watir不显示完整的HTML?如果我有不同框架中的元素或由Javascript初始化函数动态插入的元素,是否可以使用Watir访问它们?谢谢 最佳答案 如果元素在框架中,你必须使用这样的东西:browser.

  10. ruby 认为我在引用一个顶级常量,即使我指定了完整的命名空间 - 2

    在我的应用程序中我有classUserincludeUser::FooendUser::Foo定义在app/models/user/foo.rb现在我正在使用一个定义了自己的Foo类的库。我收到此错误:warning:toplevelconstantFooreferencedbyUser::FooUser仅引用具有完整路径的Foo,User::Foo,而Foo实际上从来没有指的是Foo。这是怎么回事?更新:才想起我之前遇到过同样的问题,在问题1中看到这里:HowdoIrefertoasubmodule's"fullpath"inruby? 最佳答案

随机推荐