Swift从相册选择图片,图文混排并且可以保存、上传数据

2023-05-16

博主最近突发奇想想做一个自己的日记本App,在过程中遇到了一些坑,摸索了很久才做出一个简单的日记本功能。

先来看看一下效果吧:
这里写图片描述

先来说说这次用到的一些东西吧:
1、UIImagePickerController:用来获取Photos里面的照片
2、UITexeView:用来做图文混排
3、NSKeyedArchiver和NSKeyedUnarchiver:保存和读取数据
具体的一些细节在过程中讲解。

从照片选择图片

首先,我们要实现从用户的Photos(照片)这个应用中读取用户的照片。最简单的方法就是用UIImagePickerController,要使用它,需要类遵循UIImagePickerControllerDelegate和UINavigationControllerDelegate这两个协议。
在做图片选择功能时,博主将其封装为三个函数(其中两个是协议中的函数)
第一个函数如下:

/// 选择图片
    @objc func pickImage() {
        self.imagePickerController = UIImagePickerController()
        //设置代理
        self.imagePickerController.delegate = self
        //允许用户对选择的图片或影片进行编辑
        self.imagePickerController.allowsEditing = true
        //设置image picker的用户界面
        self.imagePickerController.sourceType = .photoLibrary
        //设置图片选择控制器导航栏的背景颜色
        self.imagePickerController.navigationBar.barTintColor = UIColor.orange
        //设置图片选择控制器导航栏的标题颜色
        self.imagePickerController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
        //设置图片选择控制器导航栏中按钮的文字颜色
        self.imagePickerController.navigationBar.tintColor = UIColor.white
        //显示图片选择控制器
        self.present(self.imagePickerController, animated: true, completion: nil)
    }

这个函数中的东西都很简单,需要说的就只有一个那就是设置imagePickerController的sourceType,它的类型是UIImagePickerControllerSourceType的枚举,其中三个变量分别为photoLibrary(照片库)、camera(相机)、savedPhotosAlbum(保存的相册)。设置sourceType就是设置图片的来源,常用的为前两个。
然后就是两个协议中的方法了,一个是你选择了对应的图片

/// 图片选择完成
    ///
    /// - Parameters:
    ///   - picker: 图片选择控制器
    ///   - info: 图片信息
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//        print("media type: \(String(describing: info["UIImagePickerControllerMediaType"]))")
//        print("crop rect: \(String(describing: info["UIImagePickerControllerCropRect"]))")
//        print("reference url: \(String(describing: info["UIImagePickerControllerReferenceURL"]))")
        //获取选择到的图片
        let image = info["UIImagePickerControllerEditedImage"] as? UIImage
        //将图片加入到textView中
        addImage(image: image!)
        //关闭当前界面
        self.dismiss(animated: true, completion: nil)
    }

首先用获取到的info属性来获取你选中的相片,info是一个[String:Any]类型的字典,字典中有一些系统定义的key,这儿简单列举一下:

didFinishPickingMediaWithInfo参数的键值对:
UIImagePickerControllerMediaType: 用户选择的媒体类型,如kUTTypeImage or kUTTypeMovie
UIImagePickerControllerOriginalImage: 用户选择的未经剪裁的原始图片素材
UIImagePickerControllerEditedImage: 用户选择的经过编辑之后的图片素材
UIImagePickerControllerCropRect: 用户对原始图片进行剪裁的区域
UIImagePickerControllerMediaURL: 用户选择的影片素材在文件系统中的位置
UIImagePickerControllerReferenceURL: 用户选择的原始图片在文件系统中的位置。即使用户对图片或影片进行了编辑,仍然会返回原始素材的位置
UIImagePickerControllerMediaMetadata: 新拍摄的图片的meta信息。只有当source type为相机时才会返回该信息
UIImagePickerControllerLivePhoto: 用户选择的活拍摄的live photo。仅支持iOS 9.1及之后的版本

我们这里使用的是编辑过后的照片,然后在调用dismiss方法关闭当前的界面。
另一个就是在选择照片的过程中取消选择,这个方法很简单,直接调用dismiss关闭界面就可以了。代码如下:

/// 取消选择图片
    ///
    /// - Parameter picker: 图片选择控制器
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.dismiss(animated: true, completion: nil)
    }

到这里,就实现了一个简单的图片选择器。

UITextView图文混排

其次,就是将获取到的图片在UITextView中显示。

@objc func addImage(image: UIImage) {
        //创建文本附件
        let attachment = NSTextAttachment()
        //设置附件的图片
        attachment.image = image
        //图片的缩放比例
        let scale = (textView.frame.width - 2 * 5 ) / image.size.width
        //设置附件的大小
        attachment.bounds = CGRect(x: 0, y: 0, width: scale * image.size.width, height: scale * image.size.height)
        //获取textView中的富文本
        let attribute = NSMutableAttributedString(attributedString: textView.attributedText)
        //在富文本中加入图片附件
        attribute.append(NSAttributedString(attachment: attachment))
        //设置textView中的富文本
        textView.attributedText = attribute
    }

这里要说一下的就是,你获取到的图片的大小往往比屏幕大很多,所以需要将图片缩放一下,当初这里百度了几十分钟才找到,原来只需要设置一下attachment的bounds就可以了,只能说百度太坑。

NSAttributedString(图文混排)保存与读取

最后就是将textView中的富文本保存和读取了,这个困惑了博主很久,因为第一时间想的是找教程,而不是看Swift的API,所以浪费了很多时间,在保存数据时耽误了很久,读取数据并显示时,耽误了更久。
先看看保存数据的代码吧:

@objc func nextPage() {

        var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        url?.appendPathComponent("text.txt")

        let attribute = textView.attributedText

        let data = NSKeyedArchiver.archivedData(withRootObject: attribute as Any)
        do {
            try data.write(to: url!)
        } catch {
            print(error)
        }

        navigationController?.pushViewController(MyViewController(), animated: true)
    }

我这里将其放在了跳转页面的过程中,因为只需要功能,所以没考虑效率、布局和MVC等。最开始博主以为可以将富文本转换成AnyObject来保存数据,可是读取出来,只有其中的文本内容,图片消失不见了,debug时才知道NSTextAttachment(附件)虽然在富文本当中,但它与文字是分开的,在直接转换成AnyObject时是不会保存图片的。然后百度了很久,看了很多大牛的操作,目前只需要做一个简单的图文混排保存,并不想太复杂,所以只能自己去看API,然后,恍然大悟,因为我看到了这个
这里写图片描述
NSAttributedString遵循了NSSecureCoding协议,这个协议是继承自NSCoding协议的。所以我们就可以直接用NSKeyedArchiver来编码数据并保存了(当时那个心情啊,直接放了几个小时三天三夜,室友都在旁边磨西瓜刀了)

NSKeyedArchiver怎么用?看这篇文章

本以为事情到这里就结束了,然而,编程就是这么有趣,又是几个小时的时间。算了,都是泪,先看代码:

private func getContent() {
        var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        url?.appendPathComponent("text.txt")
        if let data = try? Data(contentsOf: url!) {
            let attribute = NSMutableAttributedString(attributedString: NSKeyedUnarchiver.unarchiveObject(with: data) as! NSAttributedString)
            //枚举出富文本中所有的内容
            attribute.enumerateAttributes(in: NSRange(location: 0, length: attribute.length), options: [], using: { (data, range, _) in
                //找出富文本中的附件
                if let attachment = data[.attachment] as? NSTextAttachment {
                    //取出附件中的图片
                    let image = (attachment.image)!
                    //缩放
                    let scale = (textView.frame.width - 2 * 5 ) / image.size.width
                    //设置大小
                    attachment.bounds = CGRect(x: 0, y: 0, width: image.size.width * scale, height: image.size.height * scale)
                    //替换富文本中的附件
                    attribute.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment))
                }
            })
            textView.attributedText = attribute
        }
    }

最开始本以为将数据解码,就能正常显示了,但是,图片,又变成原大小了,想想也是有原因的,在开始时我们设置的只是attachment(附件)的大小,而并没有修改图片的尺寸,所以在保存时,保存的当然就是原图,读取出来之后并没有设置其大小的代码,当然它就会以原图显示。所以,继续百度,其中有注释的内容就是百度了很久才百度到的。

原处是CSDN的小伙伴写的博文

最后附上所有代码:

AppDelegate.swift

window?.rootViewController = UINavigationController(rootViewController: ViewController())

修改App根视图为导航栏控制器

ViewController.swift

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    var textView: UITextView!
    var imagePickerController: UIImagePickerController!

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "write"

        let next = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(nextPage))
        navigationItem.rightBarButtonItem = next

        let add = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(pickImage))
        navigationItem.leftBarButtonItem = add

        textView = UITextView(frame: self.view.frame)
        textView.font = UIFont.systemFont(ofSize: 36)
        textView.becomeFirstResponder()
        self.view.addSubview(textView)
    }

    @objc func addImage(image: UIImage) {
        let attachment = NSTextAttachment()
        attachment.image = image
        let scale = (textView.frame.width - 2 * 5 ) / image.size.width
        attachment.bounds = CGRect(x: 0, y: 0, width: scale * image.size.width, height: scale * image.size.height)

        let attribute = NSMutableAttributedString(attributedString: textView.attributedText)
        attribute.append(NSAttributedString(attachment: attachment))

        textView.attributedText = attribute
    }


    @objc func nextPage() {

        var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        url?.appendPathComponent("text.txt")

        let attribute = textView.attributedText

        let data = NSKeyedArchiver.archivedData(withRootObject: attribute as Any)
        do {
            try data.write(to: url!)
        } catch {
            print(error)
        }

        navigationController?.pushViewController(MyViewController(), animated: true)
    }


    /// 选择图片
    @objc func pickImage() {
        self.imagePickerController = UIImagePickerController()
        //设置代理
        self.imagePickerController.delegate = self
        //允许用户对选择的图片或影片进行编辑
        self.imagePickerController.allowsEditing = true
        //设置image picker的用户界面
        self.imagePickerController.sourceType = .photoLibrary
        //设置图片选择控制器导航栏的背景颜色
        self.imagePickerController.navigationBar.barTintColor = UIColor.orange
        //设置图片选择控制器导航栏的标题颜色
        self.imagePickerController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
        //设置图片选择控制器导航栏中按钮的文字颜色
        self.imagePickerController.navigationBar.tintColor = UIColor.white
        //显示图片选择控制器
        self.present(self.imagePickerController, animated: true, completion: nil)
    }


    /// 图片选择完成
    ///
    /// - Parameters:
    ///   - picker: 图片选择控制器
    ///   - info: 图片信息
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//        print("media type: \(String(describing: info["UIImagePickerControllerMediaType"]))")
//        print("crop rect: \(String(describing: info["UIImagePickerControllerCropRect"]))")
//        print("reference url: \(String(describing: info["UIImagePickerControllerReferenceURL"]))")

        let image = info["UIImagePickerControllerEditedImage"] as? UIImage

        addImage(image: image!)

        self.dismiss(animated: true, completion: nil)
    }


    /// 取消选择图片
    ///
    /// - Parameter picker: 图片选择控制器
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.dismiss(animated: true, completion: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

MyViewController.swift

import UIKit

class MyViewController: UIViewController {

    var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "read"

        textView = UITextView(frame: self.view.frame)
        textView.isEditable = false
        self.view.addSubview(textView)

        getContent()

    }

    private func getContent() {
        var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        url?.appendPathComponent("text.txt")
        if let data = try? Data(contentsOf: url!) {
            let attribute = NSMutableAttributedString(attributedString: NSKeyedUnarchiver.unarchiveObject(with: data) as! NSAttributedString)
            //枚举出富文本中所有的内容
            attribute.enumerateAttributes(in: NSRange(location: 0, length: attribute.length), options: [], using: { (data, range, _) in
                //找出富文本中的附件
                if let attachment = data[.attachment] as? NSTextAttachment {
                    //取出附件中的图片
                    let image = (attachment.image)!
                    //缩放
                    let scale = (textView.frame.width - 2 * 5 ) / image.size.width
                    //设置大小
                    attachment.bounds = CGRect(x: 0, y: 0, width: image.size.width * scale, height: image.size.height * scale)
                    //替换富文本中的附件
                    attribute.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment))
                }
            })
            textView.attributedText = attribute
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

老实说,这个效果,只能满足基本需求。博主下一篇博文会介绍更漂亮一点的图文混排;再下一篇会升级图片选择,可以一次选择多张照片,敬请期待!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift从相册选择图片,图文混排并且可以保存、上传数据 的相关文章

  • 参加2020Jam初赛记录与部分题目解答

    Google Jam大赛是谷歌举办的一年一届的在线答算法题的的比赛 初赛比赛时长27小时 xff0c 一共有5道算法题 xff0c 总分100分 xff0c 获得分数30分和以上者 xff0c 就能晋级下一轮比赛 在这27小时内 xff0c
  • Cannot add task wrapper as a task with that name already exists - 问题解决

    问题描述 项目使用 gradle build 去打包 xff0c 报错 Cannot add task 39 wrapper 39 as a task with that name already exists xff0c 使用 gradl
  • K3s 无法下载镜像 failed to authorize/ failed to fetch anonymous token/ unexpected status/ 401 Unauthorized

    我需要部署公司功能节点进行测试 xff0c 考虑自己的 mac pro 内存很小只有 16g xff0c k8s 运行需要大量内存 xff0c 电脑可能要卡死 周边同学推荐装 k3s xff0c 它可以看作 k8s 的精简版 xff0c 删
  • 一看就懂的 RabbitMQ 使用教程

    一天 xff0c 阿强接到一个需求 xff0c 将公网的服务的执行结果通知到内网的服务上 阿强一想 xff0c 很简单阿 xff0c 只要在公网搭一个简单的消息服务 xff0c 给公网系统提供一个存储消息接口 xff1b 给内网系统提供一个
  • OOM 很可怕吗 -- minio-client 上传文件触发 OOM 排错

    不要把 OOM 问题当作一个可怕的难题 xff0c 也许对着报错堆栈日志看代码就能解决 问题描述 线上服务出现 OOM 的日志 xff0c 日志显示是 minio client 的错误 使用 minio client 版本是 3 0 10
  • AI 写代码来了 - github 的 AI 写代码插件 copilot 发布

    以前老在调侃 AI 自动写代码 xff0c 没想到这么快就成现实 这几天 github 出了 AI 写代码插件 xff0c 支持 vscode 编辑器 xff0c js xff0c py xff0c go 等语言 xff0c 看了介绍 xf
  • 枚举与字符串的转换

    枚举类型的使用优势没啥好说的 但经常需要将它与字串进行转换方便显示或其它需求 1 将枚举中的标示转成字符串 xff1a define enumToString value 64 value 将枚举转换成字符串 2 在常见的方案中 xff0c
  • springcloud trace SDK 自研方案

    SDK 形式 xff0c 利用 threadlocal 实现 trace http grpc rabbitMQ springcloud gateway 异步线程池这类常见场景 客户端在协议 header 中增加 x request id x
  • fluent-bit 按 pod 名生成不同索引

    1 实现效果 如果 pod 名为 prod xff0c 输出索引名为 prod 2021 01 24 EFK 版本 xff1a es 7 12 fluent bit 1 7 5 kibana 7 12 2 实现方式 读取日志数据中 kube
  • jar 迁移 mvn 私有库

    将 jar 从一个 mvn 库迁移另一个 mvn 库的办法 1 拉取 jar 到本地 mvn 库 创建拉取项目文件夹 xff0c 文件夹下创建 pom xml xff0c settings xml 两个文件 xff0c 填写要迁移的 jar
  • Elasticsearch 解决 log4j 安全漏洞 - 升级镜像

    一 概论 Apache Log4j 2 被披露出存在严重代码执行漏洞 xff0c 目前官方已发布正式安全公告及版本 xff0c 漏洞编号 xff1a CVE 2021 44228 xff0c 漏洞被利用可导致服务器被入侵等危害 公司 ES
  • Prometheus 实现 podDown 实时告警

    一 需求 每个 pod 重启 删除时 xff0c 都能发出告警 要及时和准确 二 告警架构 集群部署在 k8s 上 xff0c 告警使用 Prometheus 43 alertManager 43 prometheusManager xff
  • prometheus 告警机制 -(为什么告警发的不及时)

    为什么告警有时发的及时 xff0c 有时发的慢 数据异常到监控发出告警的时间与多个参数相关 xff0c 包括采集间隔 xff0c 扫描间隔 xff0c group 发送间隔 xff0c 告警持续时间 for 等 最长的时间为 采集间隔 43
  • prometheus 告警机制 - 我的告警为什么重发

    为什么告警总在重复发 xff0c 有时不重复发 xff0c 怎么避免 告警会在两种情况下重发 告警 group 列表中告警有变更 xff08 增加或者减少 xff09 告警持续到 repeat interval 配置的重发时间 告警 gro
  • linux 盘格式化并挂载

    一 概论 如果 linux 要格式化盘 xff0c 需要先解挂 xff0c 才能格式化 xff0c 格式化的速度比 rm rf 会快 xff0c 作用一样 如果是初始化机器挂载盘 xff08 不要解绑操作 xff09 xff0c 直接查看第
  • grafana 画富集多个指标 label 的表格

    下午5点 xff1a 老哥 xff0c 今天把业务趋势图搞出来吧 一 怎么画表格 我们的需要是做下面的视图 xff0c 他是一个表格 xff0c 而且有着多个数据源 添加图表 填入数据 xff0c 展示原始图形 转换为 table 只显示最
  • [golang] 实现 jwt 方式登录

    1 Jwt 和 Session 登录方案介绍 JSON Web Token xff08 缩写 JWT xff09 是目前流行的跨域认证解决方案 原理是生存的凭证包含标题 header xff0c 有效负载 payload 和签名组成 用户信
  • Stochastic Light Culling for VPLs on GGX Microsurfaces论文研读

    前言 好久没写博客了 xff0c 今天来共享一下最近研读的一篇论文吧 xff0c 文章中 pdf 为参考文献可自行谷歌学术下载 因为本人还是个图形学菜鸟 xff0c 所以有什么问题希望大家多多指正 Stochastic Light Cull
  • 瞎更新,container_cpu_usage_seconds_total{job=“cadvisor“} 怎么没有啦

    一 基本介绍 1 1 概论 1 1 1 故事背景 今天在同步其他团队的 grafana 监控大盘时 xff0c Prometheus 服务报告说不能找到名为 container cpu usage seconds total job 61
  • Prometheus MySQL 性能监控

    一 介绍 Prometheus 是一种开源的监控系统和时序数据库 xff0c 旨在收集和处理大量数据并提供可视化 监控警报等功能 它支持多种语言 多种部署方式 xff0c 并且非常灵活 xff0c 而且社区支持非常活跃 xff0c 为用户提

随机推荐

  • 二、nodeJS 项目架构详解(app.js + Express + Http)

    参考 xff1a https www cnblogs com ostrich sunshine p 7474471 html 其中重点文件 文件夹说明 xff1a techNode xff1a bin www 启动运行 xff08 服务端口
  • centos 安装freeswitch

    首先安装freeswitch的运行库 更新yum yum update 安装依赖 yum install y git gcc c 43 43 wget alsa lib devel autoconf automake bison broad
  • Visio、Matlab高清图片插入word文档的几种方法。

    2023 3 30 直接参考这两个就行了 xff0c 不用花里胡哨的 MATLAB 1 重要的第一步 xff0c 另存为png图片 xff1b 2 导出之前先设置分辨率 xff0c 很多期刊要求600dpi 这一步很关键 Visio 1 重
  • CTF Crypto---RSA NC不互素

    题目 span class token keyword from span Crypto span class token punctuation span Util span class token punctuation span nu
  • 看一看Ubuntu的目录结构

    先了解一下Ubuntu的目录结构 xff0c 对于后面学习Ubuntu软件安装和使用都有帮助 一 Linux没有盘符这个概念 Windows存在多个驱动器盘符 xff0c 每个盘符形成多个树形并列的情形 xff0c Linux没有盘符这个概
  • 【C语言】——结构体进阶:结构体的内存对齐(超详细)

    前言 xff1a 上一篇已经讲了结构体的基本用法 相信各位小伙伴以经学会怎么使用 但是还有一个问题没有弄明白 结构体到底多大 xff0c 占内存空间多不多 xff0c 以经系统到底怎么访问结构体内的数据的 接下来 xff0c 详细分析一下结
  • [OpenCV实战]15 基于深度学习的目标跟踪算法GOTURN

    目录 1 什么是对象跟踪和GOTURN 2 在OpenCV中使用GOTURN 3 GOTURN优缺点 4 参考 在这篇文章中 xff0c 我们将学习一种基于深度学习的目标跟踪算法GOTURN GOTURN在Caffe中搭建 xff0c 现在
  • **在Linux的shell脚本里激活conda 虚拟环境**

    在Linux的shell脚本里激活conda 虚拟环境 之前突发其想 xff0c 既然在命令行可以通过conda activate tf激活tf的虚拟环境 xff0c 那么能不能写个脚本实现呢 xff1f 费了好大劲 xff0c 发现并不行
  • Hierarchical Russian Roulette for Vertex Connections论文研读

    第二篇论文研读文章了 xff0c 虽然依旧很菜 xff0c 但这一篇开始就相对轻松一点了 文档种有些问题 xff0c 其中所有 实时 应该替换为 高效 Hierarchical Russian Roulette for Vertex Con
  • ARM通用中断控制器GIC之中断控制

    在阅读本章之前 xff0c 可以参考笔者之前关于GIC的一些描述 xff1a ARM通用中断控制器GIC generic Interrupt Controller 简介 ARM架构Generic Interrupt Controller G
  • 最小生成树之Kruskal算法

    给定一个无向图 xff0c 如果它任意两个顶点都联通并且是一棵树 xff0c 那么我们就称之为生成树 Spanning Tree 如果是带权值的无向图 xff0c 那么权值之和最小的生成树 xff0c 我们就称之为最小生成树 MST Min
  • xcode11解决:xcode multiple commands produce .../xxx/Assets.car

    最近在xcode 11上使用pod碰到一个问题 xff0c Assets car被生成多次 问题如下 xff1a Multiple commands produce 39 Users luowei Library Developer Xco
  • 算法 —— 冒泡排序

    冒泡排序 冒泡排序是比较两个相邻元素 xff0c 如果它们不符合预期的顺序就交换的一个排序过程 冒泡排序就像水中气泡上升到水面的运动一样 xff0c 数组的每个元素在每次迭代中都把当前迭中最大 或最小 的元素移动到最后 xff0c 因此被称
  • UICollectionView viewForSupplementaryElementOfKind 不调用

    发现UICollectionView 的 方法不调用 func collectionView collectionView UICollectionView viewForSupplementaryElementOfKind kind St
  • UICollectionViewCell 自动大小的两种常用方式

    方法一 xff1a 自动计算 override func viewDidLoad super viewDidLoad if let flowLayout 61 collectionView collectionViewLayout as U
  • UITableViewCell 图片自适应

    常见的一种方法是异步Completed时 xff0c 根据图片大小计算cell的高度并缓存到字典里后 xff0c 刷新tableView或indexPath 但这里介绍另一种更好的方式是使用约束处理 xff0c 对imageView的上下左
  • Swift编译死锁问题

    最近在Swift OC混编项目里遇到个奇怪的问题 xff0c 这样一行代码尽然引发了Swift编译过程死锁 xxSwiftModel salary 61 xxOCModel salary doubleValue 如果哪位大神知道根因 xff
  • 多线程及聊天室程序

    1 一个多线程程序 新建一个 win32 console application 取名 xff1a MultiThread 选空的工程 xff0c 并建立一个名为 MultiThread 的源文件编辑 xff1a include inclu
  • SQL Server 2008语句大全完整版

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 设置内存选项 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • Swift从相册选择图片,图文混排并且可以保存、上传数据

    博主最近突发奇想想做一个自己的日记本App xff0c 在过程中遇到了一些坑 xff0c 摸索了很久才做出一个简单的日记本功能 先来看看一下效果吧 xff1a 先来说说这次用到的一些东西吧 xff1a 1 UIImagePickerCont