Android工程师的IOS开发记录

一、 snapkit 嵌套 scrollview

需要确定左右布局 因为是垂直滚动,参考代码如下

view.addSubview(scrollView)
        scrollView.snp.makeConstraints { (make) in
            make.edges.equalTo(view)
        }
        scrollView.addSubview(contentView)
        contentView.snp.makeConstraints { make in
            make.top.bottom.equalTo(scrollView)
            make.left.right.equalTo(view) // 确定的宽度,因为垂直滚动 }


二、 snapkit 无法滑动 scrollView 无法滑动

检查 scrollView 中最顶部布局是否有,参考代码如下

top.equalToSuperview()

检查布局底部是否有置底部,参考代码如下

bottom.equalToSuperview()


三、 snapkit 框架实现横向 "TableView"

iOS 开发中 TableView 的横向布局采用的普遍方案是讲 tableView 旋转 90 度后再将自定义 cell 逆时针旋转 90

tableView.transform = CGAffineTransformMakeRotation(-Double.pi / 2)
cell.transform = CGAffineTransformMakeRotation(.pi / 2)

而我们如果采用 snap kit 框架通过添加约束的方法进行横向布局会出现宽度错乱的问题 所以 我的解决方法是自己写个算法一个个添加子 View

核心解决算法参考如下

        for index in 0...topSelectUIViewArray.count-1{
            if index == 0{
                topSelectUIViewArray[index].snp.makeConstraints { make in
                    make.top.left.bottom.equalToSuperview()
                    make.width.equalTo(30)
                }
                //在 topSelectUIViewArray[index]这个view中可以继续添加布局,就像自定义cell一样
            }else{
                topSelectUIViewArray[index].snp.makeConstraints { make in
                    make.left.equalTo(topSelectUIViewArray[index].snp.right)
                    make.top.bottom.equalToSuperview()
                    make.width.equalTo(30)
                }
            }
        }


四、 当遇到数据量复杂的页面时 比如说局部横向滑动 局部上下滑动 就可以采用嵌套 UIViewController 的方案来解决,类似于Android中activity嵌套不同的fragment

container.addSubview(basketball.view)
        vc1.view.snp.makeConstraints { make in
            make.top.left.right.bottom.equalToSuperview()
        }
        vc1.didMove(toParent: self)


如果要去除可以使用

 vc1.willMove(toParent: nil)
            vc1.removeFromParent()
            vc1.view.removeFromSuperview()


五、 view 点按效果

这点 ios 跟安卓的区别很大 安卓官方提供了水波纹的功能实现点按效果 我的解决方案是自定义 view 来实现,参考代码如下

//
//  UIViewEffect.swift
//  competition
//
//  Created by cyy on 2023/8/7.
//
 
import UIKit
 
class UIViewEffect: UIView {
    var backColor = UIColor.white
    var effectColor = UIColor.colorWithHexString("#F2F3F5")
    
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        backColor = backgroundColor ?? UIColor.white
        self.backgroundColor = effectColor
    }
    
    override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
        UIView.animate(withDuration: 0.15, animations: { () -> id in
            self.backgroundColor = self.backColor
        })
    }
 
    override func touchesEnded(_ touches: Set, with event: UIEvent?) {
        UIView.animate(withDuration: 0.15, animations: { () -> Void in
            self.backgroundColor = self.backColor
        })
    }
}

 

六、 ios 多文件分享和单个文件分享

当时做这个的时候遇到了很多的坑

self.documentInteractionController = UIDocumentInteractionController(url: shareurl)
                        self.documentInteractionController?.name = self.fileTypeArrary[row].name
                        self.documentInteractionController?.presentOptionsMenu(from: self.view.bounds, in: self.view, animated: true)


需要注意的是, documentInteractionController 这个类必须声明为全局变量 然后在局部方法中进行实例化 否则无法使用

var documentInteractionController: UIDocumentInteractionController?

上面的代码只能进行单个文件分享 如果需要分享多个文件的话 ,还需 要采用另外的方法,参考代码如下

let ui=UIActivityViewController(activityItems: [shareurl], applicationActivities: nil)
            self.present(ui, animated:true, completion: nil)


七、 iOS 自定义 UITableViewCell 宽度 320 问题

很多时候我们需要在自定义的 UITableViewCell 中进行宽度识别才能做 ui 而在 UITableViewCell 初始化中默认的宽高永远是 320 * 44 网上的解决方案是在

  override func layoutSubviews() {
        initView()
    }

中进行 ui 操作 但是在这个方法中进行操作会导致频繁执行布局操作 当数据多时严重影响性能

解决方案是 在外部提前定义好真实的宽度并传入使用

 

八、 UITableView 去掉下划线需要在addSubview 之后执行

iOS UITableView 每个 item 会默认有个下划线 如果要去除下划线的代码如下

方案1:
dataTableView.separatorStyle = UITableViewCell.SeparatorStyle.none
方案2:
tableView.separatorColor = .clear

个人推荐方案 1 无论 1 还是 2 都需要在 addSubview 后执行 否则无效

 

九、 UITableView 复用 布局 的问题

UITableView 的逻辑中 当创建多个 cell 并且屏幕显示不了所有的 cell 时,系统会将多余没有显示到的 cell 放入复用池 (reuse pool) 中,当需要新建 cell 并且标识符与复用池中的标识符存在相同的情况,就会调用复用池中的 cell ,并且会使用该 cell 的所有 UI 控件 在定义 UITableView 有个方法

TableView.register(NSClassFromString("UITableViewCell"), forCellReuseIdentifier: "TableViewCellId")

其中 TableViewCellId 就是固定的 id 在自定义 cell 中加入 id 用于区分不同的 item 可以有效避免数据错乱的问题

var cell:TableViewCell?=tableView.dequeueReusableCell(withIdentifier: "TableViewCellId-\(indexPath.row)-\(indexPath.section)") as? TableViewCell


十、 有时候为了方便快速开发 服务端会直接把一段 html 代码发送给我们 我们在本地可以直接执行 ios Android 一样头提供了相关的方法 我把他们整理成一个扩展函数,参考代码如下

extension String {
 public func convertHtmlToAttributedStringWithCSS() -> NSAttributedString? {
     
        guard let data = self.data(using: .utf8) else {
            return nil
        }
        do {
            return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        }
        catch {
            print(error)
            return nil
        }
    }
}


十一、 遇到一个需求 在一个高度有限且固定的布局中需要放入不同尺寸的图片 并且图片不能拉伸 最开始尝试在设置的时候之设置长度不设置宽度 后来发现这样做没办法完成需求 最后解决方案

 imgViewArray[index].contentMode = .scaleAspectFit


请使用浏览器的分享功能分享到微信等