微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift在UITableViewCell中使用UISlider是正确的方法吗?

如何解决Swift在UITableViewCell中使用UISlider是正确的方法吗?

我正在努力在UITableViewCell中正确使用UiSliders。 这是想法:

  • 用户可以设置他需要完成任务的不同工作。无法预先知道不同作业的数量。举例来说,假设User1的乐队专用吉他手和鼓手需要,而其他人则需要吉他手,鼓手,歌手,键盘手等。

我希望他提供的是,根据他所需的工作,他可以​​设置特定工作所需的人员数量。 我正在TableViewCell中使用UiSlider,让他做到这一点。

但是麻烦来了:

(1)用户拖动滑块时,UiSlider下的标签显示数量不正确 (2)prepareForReuse函数无法正常工作。我希望用户在使用重用的单元格时将Slider重新设置为0,并将Label显示为0。 (3)最后,jobAmountNeeded 数组没有存储正确的值(或根本没有任何值),因此在Firebase中保存的数量不正确。

我认为所有三个问题都连接到同一来源。

因此,如果有人可以帮助我,我将非常高兴。 :)

感谢大家的帮助!

class ProjectTeamViewController: UIViewController {

    // MARK: - Properties
    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var headerSeperator: UIView!
    @IBOutlet weak var saveButton: UIButton!
    
    
    var sortedSoloJobs = [String]()
    
    var jobIndex: Int?
    var jobAmount: [String] = []
    var selectedJob:String?
    var sentProjectCreated:String?
    var projectCreated:String?
    var jobAmountNeeded = [JobNeeded]()
    

       
    var slider: [SliderClass] = []
    
    let step:Float = 1
    
    var selectedindexPath: IndexPath?
    
    var tempArray = [99: "Baum"]
    var tempArray2 = [99: 5]
    var currentValue:Float = 0
    var key = 0
    


    override func viewDidLoad() {
        super.viewDidLoad()

        setUpUI ()
        getJobs(for: User.current) { (memberJobs) in
            self.tableView.reloadData()
        }

    }
    
    
    // MARK: - Functions
    
        func setUpUI () {
            Utilities.addShadowtoView(headerSeperator)
            Utilities.addShadowtoButton(saveButton)
            saveButton.layer.cornerRadius = 6
            saveButton.layer.borderWidth = 1
            saveButton.layer.borderColor = UIColor.darkGray.cgColor
            
        }

        func getJobs(for user: User,completion: @escaping ([MemberJobsstruct]) -> Void) {
            var jobs = [String]() // All Jobs
            var soloJobs = [String]() // Solo jobs from all jobs

            let ref = Database.database().reference().child("team").child(user.uid)

            ref.observeSingleEvent(of: .value,with: { snapshot in

                for case let child as DataSnapshot in snapshot.children {
                    guard let value = child.value as? [String: Any] else {
                        return completion ([]) }

                    let memberJob = value["memberJob"] as! String
                    jobs.append(memberJob)
                    soloJobs = Array(Set(jobs))
                    self.sortedSoloJobs = soloJobs.sorted()
                    
                    dispatchQueue.main.async { self.tableView.reloadData() }
            } })
        }
    func json(from object:Any) -> String? {
        guard let data = try? JSONSerialization.data(withJSONObject: object,options: []) else {
            return nil
        }
        return String(data: data,encoding: String.Encoding.utf8)
    }
  
   @objc func sliderValueChange(sender: UiSlider){
         
    sender.isContinuous = false
    currentValue = round(sender.value / step) * step
    var sliderValue = Int(currentValue)
            sender.value = currentValue   // get slider's value
            let row = sender.tag               // get slider's row in table
                key = row
    
    
   
    if let row = self.jobAmountNeeded.firstIndex(where: {$0.jobKey == key}) {
    jobAmountNeeded[row].jobAmount = sliderValue
        }
    }
    
    @IBAction func saveAction(_ sender: Any) {

        if projectCreated == nil || projectCreated == "no Value" {
            let alert = UIAlertController(title: "Error",message: "Internal Error send a bug report: #150420",preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK",style: .default,handler: nil))
                alert.addAction(UIAlertAction(title: "Cancel",handler: nil))
                self.present(alert,animated: true)
        } else {
        for value in jobAmountNeeded {
            let jobName = value.jobName
            let jobAmount = value.jobAmount
            let jobKey = value.jobKey
            let currentUser = User.current
            let jobreqRef = Database.database().reference().child("posts").child(currentUser.uid).child(projectCreated ?? "no Value").child("ProjectJobAmount").child(value.jobName)
            let project = JobNeeded(jobName: jobName,jobAmount: jobAmount,jobKey: jobKey)
            let projectDict = project.dictValue
                   jobreqRef.setValue(projectDict)  { err,jobreqRef in
//                       print("done")
            }
        }
    
        }
    }
    
    @IBAction func cancelAction(_ sender: Any) {
          self.view.window?.rootViewController?.dismiss(animated: true,completion: nil)
        
    }
    
}

extension ProjectTeamViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        
        return sortedSoloJobs.count    }

    
    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let sortedSoloJob = sortedSoloJobs[indexPath.row]
        
        
        let key = indexPath.row

        let cell = tableView.dequeueReusableCell(withIdentifier: "ProjectCharacterTableViewCell",for: indexPath) as! ProjectCharacterTableViewCell
  
        cell.jobNameLabel.text = sortedSoloJobs[indexPath.row]
               
               jobAmountNeeded.append(JobNeeded(jobName: sortedSoloJob,jobAmount: 0,jobKey: indexPath.section))
               
               if let row = self.jobAmountNeeded.firstIndex(where: {$0.jobName == sortedSoloJob}) {
                   jobAmountNeeded[row].jobName = sortedSoloJob
                   }
           
             
        tempArray.updateValue(sortedSoloJob,forKey: key)

        let currentValue = cell.slider.value
        cell.slider.isContinuous = false
        cell.slider.tag = key
        cell.slider.minimumValue = 0
        cell.slider.maximumValue = Float(sortedSoloJob.count)
        cell.slider.addTarget(self,action:  #selector(sliderValueChange),for: .valueChanged)
        cell.jobAmountLabel.text = "\(currentValue)"
        return cell
            
          
        
    }
 
}
// MARK: - UITableViewDelegate

extension ProjectTeamViewController: UITableViewDelegate {
    
    func tableView(_ tableView: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat {

        return  163
       
    }

}


class SliderClass: NSObject {
    var title: String?
    var subtitle: String?
    var sliderMinimum: Float?
    var sliderMaximum: Float?

    init(title: String,subtitle: String,sliderMinimum: Float,sliderMaximum: Float) {
        self.title = title
        self.subtitle = subtitle
        self.sliderMinimum = sliderMinimum
        self.sliderMaximum = sliderMaximum

    }
}

class ProjectCharacterTableViewCell: UITableViewCell {

    
    @IBOutlet weak var jobAmountLabel: UILabel!
    @IBOutlet weak var slider: UiSlider!
    @IBOutlet weak var jobNameLabel: UILabel!
    
    
    
    
       
       override func awakeFromNib() {
           super.awakeFromNib()
            
        
    }
    
    override public func prepareForReuse() {
      // Ensures the reused cosmos view is as good as new
        super.prepareForReuse()
        self.jobAmountLabel.text = "0"
        self.slider.value = 0
    }

    override func setSelected(_ selected: Bool,animated: Bool) {
        super.setSelected(selected,animated: animated)

        // Configure the view for the selected state
    }

}

解决方法

更简单...

首先,让我们为您的SliderClass添加一个“当前值”属性(我称它为SoloJob类,这似乎更合逻辑):

class SoloJob: NSObject {
    var title: String = ""
    var subtitle: String = ""
    var sliderMinimum: Float = 0
    var sliderMaximum: Float = 100
    var currentValue: Float = 0
    
    init(title: String,subtitle: String,sliderMinimum: Float,sliderMaximum: Float,currentValue: Float) {
        self.title = title
        self.subtitle = subtitle
        self.sliderMinimum = sliderMinimum
        self.sliderMaximum = sliderMaximum
        self.currentValue = currentValue
    }
}

我们将使用currentValue属性来跟踪滑块值。

因此,创建一个带有“标题”标签,一个滑块和一个“作业数量”(或当前值)标签的单元格。我的布局是这样的:

enter image description here

在您的单元格类中,将滑块连接到@IBAction,以了解其更改的时间-控制器类中的

也在您的单元格类中,添加一个“回调”闭包变量:

// closure to tell controller the slider was changed
var callback: ((Float) -> ())?

然后,在您的@IBAction函数中:

@IBAction func sliderValueChange(_ sender: UISlider) -> Void {
    let v = sender.value
    // update the label
    jobAmountLabel.text = "Current Amount: \(Int(v))"
    // tell the controller the slider changed
    callback?(v)
}

返回您的控制器类,在cellForRowAt中,设置“回调”闭包:

func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: "ProjectCharacterTableViewCell",for: indexPath) as! ProjectCharacterTableViewCell
    
    let thisJob: SoloJob = sortedSoloJobs[indexPath.row]
    
    // set values / labels in the cell
    
    // closure to get notified when the slider is changed
    cell.callback = { val in
        // update our data
        self.sortedSoloJobs[indexPath.row].currentValue = val
    }

    return cell

}

当用户拖动滑块时,将调用单元格类本身中的@IBAction func sliderValueChange() ,这就是我们在单元格中更新标签的地方,控制器的值已更改。

这是一个完整的实现:

import UIKit

class SoloJob: NSObject {
    var title: String = ""
    var subtitle: String = ""
    var sliderMinimum: Float = 0
    var sliderMaximum: Float = 100
    var currentValue: Float = 0
    
    init(title: String,currentValue: Float) {
        self.title = title
        self.subtitle = subtitle
        self.sliderMinimum = sliderMinimum
        self.sliderMaximum = sliderMaximum
        self.currentValue = currentValue
    }
}

class ProjectCharacterTableViewCell: UITableViewCell {
    
    @IBOutlet weak var jobAmountLabel: UILabel!
    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var jobNameLabel: UILabel!
    
    // closure to tell controller the slider was changed
    var callback: ((Float) -> ())?
    
    override init(style: UITableViewCell.CellStyle,reuseIdentifier: String?) {
        super.init(style: style,reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        contentView.layer.cornerRadius = 12
        contentView.layer.borderColor = UIColor.blue.cgColor
        contentView.layer.borderWidth = 1
        contentView.layer.masksToBounds = true
        contentView.backgroundColor = .white
        backgroundColor = .clear
    }
    func configureCell(_ theJob: SoloJob) -> Void {
        jobNameLabel.text = theJob.title + " - min: \(Int(theJob.sliderMinimum)) / max: \(Int(theJob.sliderMaximum))"
        slider.minimumValue = theJob.sliderMinimum
        slider.maximumValue = theJob.sliderMaximum
        slider.value = theJob.currentValue
        jobAmountLabel.text = "Current Amount: \(Int(theJob.currentValue))"
    }
    
    // connect valueChanged action in Storyboard
    @IBAction func sliderValueChange(_ sender: UISlider) -> Void {
        let v = sender.value
        // update the label
        jobAmountLabel.text = "Current Amount: \(Int(v))"
        // tell the controller the slider changed
        callback?(v)
    }
}

class ProjectTeamViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    var sortedSoloJobs: [SoloJob] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // create some example data
        for i in 1...20 {
            // random slider minimum between 0 and 2
            let minVal = Int.random(in: 0...2)
            // random slider maximum between 5 and 10
            let maxVal = Int.random(in: 5...10)
            // start with current value at minimum
            let curVal = minVal
            let job = SoloJob(title: "Job Name \(i)",subtitle: "",sliderMinimum: Float(minVal),sliderMaximum: Float(maxVal),currentValue: Float(curVal))
            sortedSoloJobs.append(job)
        }
        
        tableView.dataSource = self
        tableView.delegate = self
        
    }
 
}

extension ProjectTeamViewController: UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return sortedSoloJobs.count
    }
    
    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "ProjectCharacterTableViewCell",for: indexPath) as! ProjectCharacterTableViewCell
        
        let thisJob: SoloJob = sortedSoloJobs[indexPath.row]
        
        cell.configureCell(thisJob)
        
        // closure to get notified when the slider is changed
        cell.callback = { val in
            // update our data
            self.sortedSoloJobs[indexPath.row].currentValue = val
        }

        return cell

    }
    
}

extension ProjectTeamViewController: UITableViewDelegate {
}

和情节提要源(具有所有@IBOutlet@IBAction连接):

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="OoM-UM-qa5">
    <device id="retina4_0" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Project Team View Controller-->
        <scene sceneID="LA9-sV-8lR">
            <objects>
                <viewController id="OoM-UM-qa5" customClass="ProjectTeamViewController" customModule="TableAdd" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="GWK-to-6GG">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="I5Z-lW-4b3">
                                <rect key="frame" x="20" y="20" width="280" height="30"/>
                                <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <state key="normal" title="SAVE BUTTON"/>
                            </button>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Rkw-MO-6Op" userLabel="Horizontal Line View">
                                <rect key="frame" x="20" y="58" width="280" height="1"/>
                                <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="1" id="BkU-lx-Zp8"/>
                                </constraints>
                            </view>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="pgu-lS-tk6">
                                <rect key="frame" x="20" y="67" width="280" height="481"/>
                                <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                                <prototypes>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ProjectCharacterTableViewCell" rowHeight="109" id="tnK-1p-f4N" customClass="ProjectCharacterTableViewCell" customModule="TableAdd" customModuleProvider="target">
                                        <rect key="frame" x="0.0" y="28" width="280" height="109"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="tnK-1p-f4N" id="gcG-sV-dlw">
                                            <rect key="frame" x="0.0" y="0.0" width="280" height="109"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Job Name Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l3R-9V-mjm">
                                                    <rect key="frame" x="78" y="11" width="124" height="21"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="mj1-CV-iWZ">
                                                    <rect key="frame" x="13" y="36" width="254" height="31"/>
                                                    <connections>
                                                        <action selector="sliderValueChange:" destination="tnK-1p-f4N" eventType="valueChanged" id="RkI-oL-0eQ"/>
                                                    </connections>
                                                </slider>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Job Amount Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xMH-9r-GO9">
                                                    <rect key="frame" x="70.5" y="70" width="139" height="21"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                            <constraints>
                                                <constraint firstItem="l3R-9V-mjm" firstAttribute="top" secondItem="gcG-sV-dlw" secondAttribute="topMargin" id="DPl-Kl-d1J"/>
                                                <constraint firstItem="mj1-CV-iWZ" firstAttribute="leading" secondItem="gcG-sV-dlw" secondAttribute="leadingMargin" id="Sx7-a7-Yxy"/>
                                                <constraint firstItem="mj1-CV-iWZ" firstAttribute="top" secondItem="l3R-9V-mjm" secondAttribute="bottom" constant="4" id="Z05-fI-eal"/>
                                                <constraint firstItem="xMH-9r-GO9" firstAttribute="top" secondItem="mj1-CV-iWZ" secondAttribute="bottom" constant="4" id="a8n-XL-xxa"/>
                                                <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="xMH-9r-GO9" secondAttribute="bottom" id="cg5-O7-mnS"/>
                                                <constraint firstItem="l3R-9V-mjm" firstAttribute="centerX" secondItem="gcG-sV-dlw" secondAttribute="centerX" id="hGU-ad-se2"/>
                                                <constraint firstItem="xMH-9r-GO9" firstAttribute="centerX" secondItem="gcG-sV-dlw" secondAttribute="centerX" id="p4W-nU-hxy"/>
                                                <constraint firstAttribute="trailingMargin" secondItem="mj1-CV-iWZ" secondAttribute="trailing" id="umL-5D-BUa"/>
                                            </constraints>
                                        </tableViewCellContentView>
                                        <connections>
                                            <outlet property="jobAmountLabel" destination="xMH-9r-GO9" id="AIQ-ro-Q2C"/>
                                            <outlet property="jobNameLabel" destination="l3R-9V-mjm" id="cA7-Kq-aRd"/>
                                            <outlet property="slider" destination="mj1-CV-iWZ" id="YDo-wV-0rA"/>
                                        </connections>
                                    </tableViewCell>
                                </prototypes>
                            </tableView>
                        </subviews>
                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                        <constraints>
                            <constraint firstItem="I5Z-lW-4b3" firstAttribute="leading" secondItem="iax-Rw-gHC" secondAttribute="leading" constant="20" id="8bZ-vh-e2L"/>
                            <constraint firstItem="pgu-lS-tk6" firstAttribute="leading" secondItem="iax-Rw-gHC" secondAttribute="leading" constant="20" id="KK9-MN-7TR"/>
                            <constraint firstItem="I5Z-lW-4b3" firstAttribute="top" secondItem="iax-Rw-gHC" secondAttribute="top" constant="20" id="MBM-in-OG7"/>
                            <constraint firstItem="Rkw-MO-6Op" firstAttribute="leading" secondItem="iax-Rw-gHC" secondAttribute="leading" constant="20" id="NM3-Ah-IIR"/>
                            <constraint firstItem="pgu-lS-tk6" firstAttribute="top" secondItem="Rkw-MO-6Op" secondAttribute="bottom" constant="8" id="abw-Kr-4qh"/>
                            <constraint firstItem="iax-Rw-gHC" firstAttribute="bottom" secondItem="pgu-lS-tk6" secondAttribute="bottom" constant="20" id="dBK-83-lBg"/>
                            <constraint firstItem="iax-Rw-gHC" firstAttribute="trailing" secondItem="I5Z-lW-4b3" secondAttribute="trailing" constant="20" id="erM-u3-zLO"/>
                            <constraint firstItem="Rkw-MO-6Op" firstAttribute="top" secondItem="I5Z-lW-4b3" secondAttribute="bottom" constant="8" id="ry1-D5-U89"/>
                            <constraint firstItem="iax-Rw-gHC" firstAttribute="trailing" secondItem="Rkw-MO-6Op" secondAttribute="trailing" constant="20" id="vhe-jw-Dnb"/>
                            <constraint firstItem="iax-Rw-gHC" firstAttribute="trailing" secondItem="pgu-lS-tk6" secondAttribute="trailing" constant="20" id="zdu-4p-FAt"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="iax-Rw-gHC"/>
                    </view>
                    <connections>
                        <outlet property="tableView" destination="pgu-lS-tk6" id="08E-xc-PqA"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="Ns0-iW-ioz" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-534.375" y="839.78873239436621"/>
        </scene>
    </scenes>
</document>

结果:

enter image description here

并且由于每当滑块更改时我们都会更新数据数组,因此我们可以滚动浏览表,并将正确配置重用单元格。

当所有这些都说得通时,将方法带到您的项目中以匹配您的布局和数据结构。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。