iOS 自定义控件-仿京东地址选择器

镇楼专用

写这个的主要是为了练习Swift的使用。

Plist文件内容

下载地址

文件读取

fileprivate class WDAddressPickerDataManger: NSObject {
    
    static let manager = WDAddressPickerDataManger()
    // 读取list文件
    func readPlistFile() -> Dictionary<String, Any> {
        let path = Bundle.main.path(forResource: "list.plist", ofType: nil) ?? ""
        let dict = NSDictionary(contentsOfFile: path)
        if dict != nil {
            return dict as! Dictionary<String, Any>
        }
        return [:]
    }
    
    // 读取所有省份
    func getProvinceNameArray() -> Array<String> {
        var array: [String] = Array()
        for item in readPlistFile().keys {
            array.append(item)
        }
        return array
    }
    
    // 读取普通省份中的城市
    func getNormalCityNameArray(with provinceName: String) -> Array<String> {
        var array: [String] = Array()
        for item in readPlistFile() {
           if item.key.contains(provinceName) {
                let name = (item.value as! Dictionary<String, Any>).keys
                for cityName in name {
                    array.append(cityName)
                }
            }
        }
        return array
    }
    
    // 读取直辖市,特区中的区
    func getSpecailCityNameArray(with provinceName: String) -> Array<String> {
        var array: [String] = Array()
        for item in readPlistFile() {
           if item.key.contains(provinceName) {
                let name = item.value as! Array<String>
                for cityName in name {
                    array.append(cityName)
                }
            }
        }
        return array
    }
    
    // 读取普通城市中的区
    func getRegionNameArray(with provinceName: String, cityName: String) -> Array<String> {
        var array: [String] = Array()
        for item in readPlistFile() {
            if item.key.contains(provinceName) {
                let provinceDic = item.value as! Dictionary<String, Array<String>>
                for city in provinceDic.keys {
                    if city.contains(cityName)  {
                        for last in provinceDic[city]! {
                            array.append(last)
                        }
                    }
                }
            }
        }
        return array
    }
}

HeaderView

提示文字,与页面消失按钮

fileprivate class WDAddressPickerHeaderView: UIView {
    
    var textLabel: UILabel!
    var clearButton: UIButton!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupSubviews() {
        backgroundColor = .white
        layer.cornerRadius = 10
        
        textLabel = UILabel()
        textLabel.text = "地址选择"
        textLabel.textColor = .black
        textLabel.font = .systemFont(ofSize: 20, weight: .bold)
        addSubview(textLabel)
        
        // 自定义按钮图片
        clearButton = UIButton(type: .custom)
        clearButton.setImage(UIImage(named: "clear"), for: .normal)
        addSubview(clearButton)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        textLabel.frame = CGRect(x: 15, y: 0, width: bounds.width / 2.0, height: bounds.height)
        let cycleWidth = (bounds.height - 10.0) / 2
        clearButton.frame = CGRect(x: bounds.width - 15 - cycleWidth, y: (bounds.height - 10.0 - cycleWidth) / 2.0, width: cycleWidth, height: cycleWidth)
    }
}

TopView

页面标题显示与切换

fileprivate class WDAddressPickerTopView: UIView {
    // 点击回调
    var didSelectedIndexBlock: ((_ index: Int) -> Void) = {(_) in}
    // 标题底部指示器
    var indicatorView: UIView!
    // 标题之间的间距
    let margin: CGFloat = 15
    // 底部指示器的布局,用来进行布局修改与动画处理
    var indicatorViewConstraints: [NSLayoutConstraint]!

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupSubviews() {
        backgroundColor = .white
        indicatorView = UIView()
        indicatorView.backgroundColor = .red
        addSubview(indicatorView)
    }
    
    // for循环显示标题
    func setup(with items: [String], selectIndex: Int) {
        var lastButton = UIButton()
        var newItems = items
        if items.isEmpty {
            newItems.append("请选择")
        }
        
        for view in subviews {
            if view.isKind(of: UIButton.self) {
                view.removeFromSuperview()
            }
        }

        for (i, title) in newItems.enumerated() {
            let button = UIButton(type: .custom)
            button.setTitle(title, for: .normal)
            button.titleLabel?.font = .systemFont(ofSize: 15, weight: .bold)
            button.setTitleColor(.black, for: .normal)
            button.addTarget(self, action: #selector(buttonTargetAction(sender:)), for: .touchUpInside)
            button.tag = 1000 + I
            addSubview(button)
            button.translatesAutoresizingMaskIntoConstraints = false
            if i == 0 {
                addConstraint(NSLayoutConstraint(item: button, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: margin))
            } else {
                addConstraint(NSLayoutConstraint(item: button, attribute: .leading, relatedBy: .equal, toItem: lastButton, attribute: .trailing, multiplier: 1, constant: margin))
            }
            addConstraints([
                NSLayoutConstraint(item: button, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)
            ])
            lastButton = button
            
            if i == selectIndex {
                indicatorView.translatesAutoresizingMaskIntoConstraints = false
                indicatorViewConstraints = [
                    NSLayoutConstraint(item: indicatorView, attribute: .leading, relatedBy: .equal, toItem: button, attribute: .leading, multiplier: 1, constant: 0),
                    NSLayoutConstraint(item: indicatorView, attribute: .trailing, relatedBy: .equal, toItem: button, attribute: .trailing, multiplier: 1, constant: 0),
                    NSLayoutConstraint(item: indicatorView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: -3),
                    NSLayoutConstraint(item: indicatorView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 5),
                ]
                addConstraints(indicatorViewConstraints)
            }
        }
    }

    
    @objc func buttonTargetAction(sender: UIButton) {
        // 移除先前添加的布局
        removeConstraints(indicatorViewConstraints)
        indicatorViewConstraints = [
            NSLayoutConstraint(item: indicatorView, attribute: .leading, relatedBy: .equal, toItem: sender, attribute: .leading, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: indicatorView, attribute: .trailing, relatedBy: .equal, toItem: sender, attribute: .trailing, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: indicatorView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: -3),
            NSLayoutConstraint(item: indicatorView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 5),
        ]
        // 添加点击变化后的布局
        addConstraints(indicatorViewConstraints)
        setNeedsUpdateConstraints()
        UIView.animate(withDuration: 0.3) {
            self.layoutIfNeeded()
        }
        didSelectedIndexBlock(sender.tag - 1000)
    }
}

列表单元格

fileprivate class WDAddressPickerTableViewCell: UITableViewCell {
    
    var titleLabel: UILabel!
    var checkedImageView: UIImageView!
        
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupSubviews()
    }
    
    required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
    }
    
    func setupSubviews() {
        titleLabel = UILabel()
        titleLabel.font = .systemFont(ofSize: 15)
        titleLabel.textColor = .black
        contentView.addSubview(titleLabel)
        
        // 自定义显示图片
        checkedImageView = UIImageView()
        checkedImageView.image = UIImage(named: "duihao")
        contentView.addSubview(checkedImageView)
    }
    
    private var _cellChecked: Bool = false
    var cellChecked: Bool {
        set {
            _cellChecked = newValue
            if !newValue {
                checkedImageView.frame = CGRect(x: 15, y: 15, width: 0, height: 0)
                titleLabel.frame = CGRect(x: 15, y: 0, width: UIScreen.main.bounds.width - 30, height: 45)
            } else {
                checkedImageView.frame = CGRect(x: 15, y: 15, width: 15, height: 15)
                titleLabel.frame = CGRect(x: checkedImageView.frame.maxX + 15, y: 0, width: UIScreen.main.bounds.width - checkedImageView.frame.maxX - 15 - 15 , height: 45)
            }
        } get {
            return _cellChecked
        }
    }
}

BottomView

底部列表视图载体,使用UIScrollView嵌套UITableView来实现

fileprivate class WDAddressPickerBottomView: UIView {
    // Action
    var didSelectedBlock: ((_ page: Int, _ index: Int, _ name: String) -> Void) = {(_,_,_) in }
    // UI
    var scrollView: UIScrollView!
    var provinceTableView: UITableView!
    var cityTableView: UITableView!
    var regionTableView: UITableView!
    // Data
    var proVinceSelectedIndexRow = -1
    var citySelectedIndexRow = -1
    var regionSelectedIndexRow = -1
    var selectedIndexRow = -1
    var regionNameArray: [String] = Array()
    var cityNameArray: [String] = Array()
    var cityName: String = "" {
        didSet {
            regionSelectedIndexRow = -1
            regionNameArray = WDAddressPickerDataManger.manager.getRegionNameArray(with: provinceName, cityName: cityName)
            regionTableView.reloadData()
        }
    }
    let provinceNameArray: [String] = WDAddressPickerDataManger.manager.getProvinceNameArray()
    var provinceName: String = "" {
        didSet {
            if provinceName.contains("北京") ||
                provinceName.contains("上海") ||
                provinceName.contains("天津") ||
                provinceName.contains("香港") ||
                provinceName.contains("澳门") ||
                provinceName.contains("重庆") {
                cityNameArray = WDAddressPickerDataManger.manager.getSpecailCityNameArray(with: provinceName)
            } else {
                cityNameArray = WDAddressPickerDataManger.manager.getNormalCityNameArray(with: provinceName)
            }
            citySelectedIndexRow = -1
            regionSelectedIndexRow = -1
            cityTableView.reloadData()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        setupSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        scrollView.frame = bounds
        provinceTableView.frame = scrollView.bounds
        cityTableView.frame = CGRect(x: scrollView.bounds.width, y: 0, width: scrollView.bounds.width, height: scrollView.bounds.height)
        regionTableView.frame = CGRect(x: scrollView.bounds.width * 2.0, y: 0, width: scrollView.bounds.width, height: scrollView.bounds.height)
    }
}

// MARK: Views Set Up
private extension WDAddressPickerBottomView {
    func setupSubviews() {
        scrollView = UIScrollView()
        scrollView.isScrollEnabled = false
        scrollView.isPagingEnabled = true
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.bounces = false
        addSubview(scrollView)

        provinceTableView = UITableView(frame: .zero, style: .plain)
        provinceTableView.delegate = self
        provinceTableView.dataSource = self
        provinceTableView.rowHeight = 45
        provinceTableView.register(WDAddressPickerTableViewCell.self, forCellReuseIdentifier: "WDAddressPickerTableViewCell")
        scrollView.addSubview(provinceTableView)
        
        cityTableView = UITableView(frame: .zero, style: .plain)
        cityTableView.delegate = self
        cityTableView.dataSource = self
        cityTableView.rowHeight = 45
        cityTableView.register(WDAddressPickerTableViewCell.self, forCellReuseIdentifier: "WDAddressPickerTableViewCell")
        scrollView.addSubview(cityTableView)
        
        regionTableView = UITableView(frame: .zero, style: .plain)
        regionTableView.delegate = self
        regionTableView.dataSource = self
        regionTableView.rowHeight = 45
        regionTableView.register(WDAddressPickerTableViewCell.self, forCellReuseIdentifier: "WDAddressPickerTableViewCell")
        scrollView.addSubview(regionTableView)
        
        scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: 0)
    }
}

// MARK: UITableView DataSource Methods
extension WDAddressPickerBottomView: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView == provinceTableView {
            return provinceNameArray.count
        } else if tableView == cityTableView {
            return cityNameArray.count
        } else {
            return regionNameArray.count
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "WDAddressPickerTableViewCell", for: indexPath) as! WDAddressPickerTableViewCell
        if tableView == provinceTableView {
            cell.titleLabel.text = (provinceNameArray[indexPath.row] as NSString).substring(from: 6)
            if indexPath.row == proVinceSelectedIndexRow {
                 cell.cellChecked = true
            } else {
                 cell.cellChecked = false
            }
         } else if tableView == cityTableView {
            cell.titleLabel.text = (cityNameArray[indexPath.row] as NSString).substring(from: 6)
            if indexPath.row == citySelectedIndexRow {
                cell.cellChecked = true
            } else {
                cell.cellChecked = false
            }
         } else {
            cell.titleLabel.text = (regionNameArray[indexPath.row] as NSString).substring(from: 6)
             if indexPath.row == regionSelectedIndexRow {
                 cell.cellChecked = true
             } else {
                 cell.cellChecked = false
             }
         }
        return cell
    }
}

// MARK: UITableView Delegate Method
extension WDAddressPickerBottomView: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let cell = tableView.cellForRow(at: indexPath) as! WDAddressPickerTableViewCell
        if tableView == provinceTableView {
            proVinceSelectedIndexRow = indexPath.row
            scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 2, height: 0)
            scrollView.setContentOffset(CGPoint(x: UIScreen.main.bounds.width, y: 0), animated: true)
        } else if tableView == cityTableView {
            citySelectedIndexRow = indexPath.row
            scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 3, height: 0)
            scrollView.setContentOffset(CGPoint(x: UIScreen.main.bounds.width * 2, y: 0), animated: true)
        } else {
            regionSelectedIndexRow = indexPath.row
        }
        tableView.reloadData()
        selectedIndexRow = indexPath.row
        didSelectedBlock(Int(scrollView.contentOffset.x / UIScreen.main.bounds.width), indexPath.row, cell.titleLabel.text ?? "")
    }
}

AddressPickerView

以上的显示的视图的载体视图

fileprivate class WDAddressPickerView: UIView {
    
    var headerView: WDAddressPickerHeaderView!
    var topView: WDAddressPickerTopView!
    var bottomView: WDAddressPickerBottomView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviews()
        setupSubviewsConstraint()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

// MARK: 页面布局
@objc private extension WDAddressPickerView {
    // 页面控件初始化
    func setupSubviews() {
        headerView = WDAddressPickerHeaderView()
        addSubview(headerView)
        
        topView = WDAddressPickerTopView()
        topView.setup(with: [], selectIndex: 0)
        addSubview(topView)
        
        bottomView = WDAddressPickerBottomView()
        addSubview(bottomView)
    }
    
    // 页面控件布局
    func setupSubviewsConstraint() {
        headerView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)
        topView.frame = CGRect(x: 0, y: headerView.frame.maxY - 10, width: UIScreen.main.bounds.width, height: 45)
        bottomView.frame = CGRect(x: 0, y: topView.frame.maxY, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 100 - topView.frame.maxY)
    }
}

地址选取管理器

class WDAddressPickerManager: NSObject {
    static let manager = WDAddressPickerManager()
    private var backView: UIView!
    private var addressPickerView: WDAddressPickerView!
    
    /// 显示选择器
    /// - Parameter completeBlock: province: 省(直辖市), city:市(直辖市中的区),region: 区
    func showPicker(completeBlock: @escaping ((_ province: String, _ city: String, _ region: String) -> Void)) {
        backView = UIView()
        backView.backgroundColor = UIColor(white: 0, alpha: 0)
        backView.frame = UIScreen.main.bounds
        backView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapGuestureTargetAction(sender:))))
        UIApplication.shared.keyWindow?.addSubview(backView)

        var titleItems: [String] = Array()
        var provinceName = ""
        var cityName = ""
        var reginName = ""
        
        addressPickerView = WDAddressPickerView()
        addressPickerView.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 100)
        addressPickerView.headerView.clearButton.addTarget(self, action: #selector(tapGuestureTargetAction(sender:)), for: .touchUpInside)
        addressPickerView.bottomView.didSelectedBlock = { [weak self] (page, index, name) in
            if page == 0 {
                provinceName = name
                cityName = ""
                reginName = ""
                titleItems = [name, "请选择"]
                self?.addressPickerView.bottomView.provinceName = name
                self?.addressPickerView.topView.setup(with: titleItems, selectIndex: page + 1)
            } else if page == 1 {
                cityName = name
                reginName = ""
                if provinceName.contains("北京") ||
                    provinceName.contains("上海") ||
                    provinceName.contains("天津") ||
                    provinceName.contains("香港") ||
                    provinceName.contains("澳门") ||
                    provinceName.contains("重庆") {
                    self?.hidenView()
                    completeBlock(provinceName, cityName, reginName)
                    return
                }
                titleItems = [(provinceName), (cityName), "请选择"]
                self?.addressPickerView.bottomView.cityName = name
                self?.addressPickerView.topView.setup(with: titleItems, selectIndex: page + 1)
            } else {
                reginName = name
                titleItems = [provinceName, cityName, reginName]
                self?.addressPickerView.topView.setup(with: titleItems, selectIndex: page)
            }
            
            if page == 2 {
                self?.hidenView()
                completeBlock(provinceName, cityName, reginName)
            }
        }
        
        addressPickerView.topView.didSelectedIndexBlock = { [weak self] index in
            self?.addressPickerView.bottomView.scrollView.setContentOffset(CGPoint(x: UIScreen.main.bounds.width * CGFloat(index), y: 0), animated: true)
        }
        
        UIApplication.shared.keyWindow?.addSubview(addressPickerView)
        
        UIView.animate(withDuration: 0.5) {
            self.backView.backgroundColor = UIColor(white: 0, alpha: 0.3)
            self.addressPickerView.frame = CGRect(x: 0, y: 100, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 100)
        }
    }
    
    @objc private func tapGuestureTargetAction(sender: Any) {
        hidenView()
    }
    
    private func hidenView() {
        UIView.animate(withDuration: 0.5, animations: {
            self.backView.backgroundColor = UIColor(white: 0, alpha: 0)
            self.addressPickerView.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 100)
        }) { (finished) in
            self.backView.removeFromSuperview()
            self.addressPickerView.removeFromSuperview()
        }
    }
}

效果图

效果.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,076评论 1 32
  • 1.badgeVaule气泡提示 2.git终端命令方法> pwd查看全部 >cd>ls >之后桌面找到文件夹内容...
    i得深刻方得S阅读 4,619评论 1 9
  • 如果可能,很想换一种方式生活 不似现在这么匆忙!这么沉重!这么乏味!这么不安!这么压抑!这么多的冲突及矛盾如临战场...
    暮山紫烟阅读 147评论 0 0
  • 我有时会用一款手机APP——番茄TODO,去淘宝上找“番茄钟”的时候得知是会发出声响的装置,故而没有真正的去了解并...
    李小罐阅读 261评论 1 1
  • 止儿文学短短一个月时间,粉丝突飞猛涨,经粉丝不断地融入了新想法,故特此安排专业团队改版,以求精益求精。 改版后我们...
    止儿徐子阅读 459评论 1 25