iOS(一):Swift纯代码模式iOS开发入门教程
创始人
2024-05-29 13:04:38
0

Swift纯代码模式iOS开发入门教程

    • 项目初始化(修改为纯代码项目)
    • 安装第三方库(以`SnapKit`库为例)
    • 桥接OC库(QMUIKit)
    • 封装视图并进行导航跳转
    • 示例:使用 `TangramKit` 第三方UI布局库
    • 应用国际化
    • 添加 `R.swift` 框架
    • 颜色统一管理(图片相同)
    • 网络请求 `Moya`
    • 网络请求 `Moya/RxSwift`
    • 解析 `json`

项目初始化(修改为纯代码项目)

1.修改 AppDelegate.swiftViewController.swift 文件

在这里插入图片描述

2.删除 SceneDelegate.swiftMain.storyboard 文件

3.修改如图所示项

在这里插入图片描述

在这里插入图片描述

安装第三方库(以SnapKit库为例)

安装CocoaPods

$ gem install cocoapods

初始化项目(添加Podfile配置文件)

$ pod init

修改Podfile文件

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'target 'ExDemoApp' do# Comment the next line if you don't want to use dynamic frameworksuse_frameworks!# Pods for ExDemoApppod 'SnapKit'end

安装

$ pod install

打开ExDemoApp.xcworkspace项目并向ViewController.swift添加示例代码

//
//  ViewController.swift
//  ExDemoApp
//
//  Created by ProsperLee on 2023/2/20.
//import UIKit
import SnapKitclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = .whitelet label: UILabel = UILabel()view.addSubview(label)label.text = "Hello"label.textColor = .redlabel.snp.makeConstraints { make inmake.centerX.equalToSuperview()make.centerY.equalToSuperview()}}}

运行效果

在这里插入图片描述

桥接OC库(QMUIKit)

安装QMUIKit

# Podfile 文件# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'target 'ExDemoApp' do# Comment the next line if you don't want to use dynamic frameworksuse_frameworks!# Pods for ExDemoApppod 'SnapKit'pod 'QMUIKit'end
$ pod install

方式一:触发xcode自动创建桥接文件机制

在这里插入图片描述

方式二:手动创建xcode桥接文件

在这里插入图片描述

在这里插入图片描述

测试桥接是否成功

在这里插入图片描述

//
//  ViewController.swift
//  ExDemoApp
//
//  Created by ProsperLee on 2023/2/20.
//import UIKit
import SnapKitclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = .whitelet button = QMUIButton()button.adjustsButtonWhenHighlighted = truebutton.setTitle("按钮", for: .normal)button.setTitleColor(.white, for: .normal)button.backgroundColor = UIColor.tintColor;button.highlightedBackgroundColor = UIColor.tintColor;button.layer.cornerRadius = 4view.addSubview(button)button.snp.makeConstraints { make inmake.width.equalTo(200)make.height.equalTo(40)make.centerX.equalToSuperview()make.centerY.equalToSuperview()}button.addTarget(self, action: #selector(buttonClick), for: UIControl.Event.touchUpInside)}@objc func buttonClick(){print("点击了")}}

封装视图并进行导航跳转

效果

在这里插入图片描述

项目目录结构

在这里插入图片描述

配置导航跳转

//
//  AppDelegate.swift
//  ExDemoApp
//import UIKit@main
class AppDelegate: UIResponder, UIApplicationDelegate {var window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller = ViewController()window = UIWindow(frame: UIScreen.main.bounds)// 包装一层导航控制器用于在视图间跳转window!.rootViewController = UINavigationController(rootViewController: controller)window?.makeKeyAndVisible()return true}}

创建要跳转到的Controller

//
//  SettingController.swift
//  设置界面
//import UIKitclass SettingController: UIViewController {override func viewDidLoad() {super.viewDidLoad()title = "设置界面"view.backgroundColor = UIColor(red: 250 / 255, green:  250 / 255, blue:  250 / 255, alpha: 1)}
}

进行跳转

//
//  ViewController.swift
//  ExDemoApp
//import UIKit
import SnapKitclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()let button = QMUIButton()button.setTitle("进入设置页面", for: .normal)view.addSubview(button)button.addTarget(self, action: #selector(goto(_:)), for: .touchUpInside)button.snp.makeConstraints{make inmake.center.equalToSuperview()}}@objc func goto(_ sender: QMUIButton){print(sender.titleLabel!.text!)let target = SettingController()navigationController?.pushViewController(target, animated: true)}
}

封装视图组件

//
//  CellView.swift
//  ExDemoApp
//import UIKit
import SnapKitclass CellView: UIView {/// 左侧图标lazy var leftIcon: UIImageView = {let v = UIImageView();v.image = UIImage(named: "Setting")return v;}()/// 单元格标题lazy var title: UILabel = {let v = UILabel();v.text = "Setting"return v;}()/// 右侧图标lazy var rightIcon: UIImageView = {let v = UIImageView();v.image = UIImage(named: "More")return v;}()// 初始化组件init() {super.init(frame: CGRect.zero)innerInit()}// 从数据中初始化一个视图(必需)required init?(coder: NSCoder) {super.init(coder: coder)innerInit()}// 组件UIView初始化func innerInit(){backgroundColor = .whiteaddSubview(leftIcon)addSubview(title)addSubview(rightIcon)}// 当view被首次添加进父级视图的时候调用override func didMoveToSuperview() {super.didMoveToSuperview()leftIcon.snp.makeConstraints{make inmake.width.equalTo(32)make.height.equalTo(32)make.centerY.equalToSuperview()make.left.equalToSuperview().offset(16)}title.snp.makeConstraints{make inmake.centerY.equalToSuperview()make.left.equalTo(leftIcon.snp.right).offset(10)}rightIcon.snp.makeConstraints{make inmake.width.equalTo(20)make.height.equalTo(20)make.centerY.equalToSuperview()make.right.equalToSuperview().offset(-16)}}}

使用组件并配置点击事件

//
//  SettingController.swift
//  设置界面
//import UIKitclass SettingController: UIViewController {// 懒加载单元格并配置相关属性lazy var cellView: CellView = {let v = CellView();v.leftIcon.image = UIImage(named: "Setting")v.title.text = "设置"// 单元格整体添加点击事件v.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onSettingClick(recognizer:))))return v;}()override func viewDidLoad() {super.viewDidLoad()title = "设置界面"view.backgroundColor = UIColor(red: 250 / 255, green:  250 / 255, blue:  250 / 255, alpha: 1)view.addSubview(cellView)cellView.snp.makeConstraints{make inmake.height.equalTo(40)make.top.equalTo(view.safeAreaLayoutGuide.snp.top);make.left.equalToSuperview()make.right.equalToSuperview()}}// 点击事件@objc func onSettingClick (recognizer:UITapGestureRecognizer){print(recognizer)cellView.title.text = "点击了!"}}

示例:使用 TangramKit 第三方UI布局库

在这里插入图片描述

pod 'TangramKit'
let horzLayout = TGLinearLayout(.horz)
horzLayout.tg_gravity = TGGravity.horz.fill  // 所有子视图水平宽度充满布局,这样就不需要分别设置每个子视图的宽度了。
horzLayout.backgroundColor = UIColor.white
horzLayout.tg_width.equal(.fill)   // 高度填充父布局的所有剩余空间。
horzLayout.tg_height.equal(60)
horzLayout.tg_bottom.equal(TGLayoutPos.tg_safeAreaMargin)
view.addSubview(horzLayout)let v1 = QMUIButton();
v1.setTitle("v1", for: .normal)
v1.backgroundColor = .red
v1.tg_height.equal(.fill)
horzLayout.addSubview(v1)let v2 = QMUIButton();
v2.setTitle("v2", for: .normal)
v2.backgroundColor = .green
v2.tg_height.equal(.fill)
horzLayout.addSubview(v2)let v3 = QMUIButton();
v3.setTitle("v3", for: .normal)
v3.backgroundColor = .blue
v3.tg_height.equal(.fill)
horzLayout.addSubview(v3)

应用国际化

引用公共字符串

在这里插入图片描述

在这里插入图片描述

/* Localizable.stringsExDemoApp
*/HomeMenuText = "首页";
//
//  ViewController.swift
//  ExDemoApp
//import UIKit
import TangramKitclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = UIColor(red: 250 / 255, green: 250 / 255, blue: 250 / 255, alpha: 1)let horzLayout = TGLinearLayout(.horz)horzLayout.tg_gravity = TGGravity.horz.fillhorzLayout.backgroundColor = UIColor.orangehorzLayout.tg_width.equal(.fill)horzLayout.tg_height.equal(60)horzLayout.tg_bottom.equal(TGLayoutPos.tg_safeAreaMargin)view.addSubview(horzLayout)let v1 = QMUILabel();v1.text = NSLocalizedString("HomeMenuText", comment: "") // 引用公共字符串v1.backgroundColor = .redv1.textAlignment = .center;v1.tg_width.equal(.fill)v1.tg_height.equal(.fill)horzLayout.addSubview(v1)let v2 = QMUILabel();v2.text = "v2"v2.backgroundColor = .greenv2.textAlignment = .center;v2.tg_width.equal(.fill)v2.tg_height.equal(.fill)horzLayout.addSubview(v2)let v3 = QMUILabel();v3.text = "v3"v3.backgroundColor = .bluev3.textAlignment = .center;v3.tg_width.equal(.fill)v3.tg_height.equal(.fill)horzLayout.addSubview(v3)}}

启用国际化(修改系统语言查看效果)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

应用名称国际化(修改系统语言查看效果)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

添加 R.swift 框架

用于优化资源获取访问的方式,如图像、字体等

1.添加依赖

pod 'R.swift'

2.创建运行脚本

在这里插入图片描述

在这里插入图片描述

"$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift"
$SRCROOT/R.generated.swift

在这里插入图片描述

3.执行编译生成 R.generated.swift 文件,并将其添加到项目根目录

在这里插入图片描述

4.使用

/* Localizable.stringsExDemoApp
*/HomeMenuText = "%@, 首页";
//
//  ViewController.swift
//  ExDemoApp
//let v1 = QMUILabel();
v1.text = NSLocalizedString(R.string.localizable.homeMenuText("你好"), comment: "")
v1.backgroundColor = .red
v1.textAlignment = .center;
v1.tg_width.equal(.fill)
v1.tg_height.equal(.fill)
horzLayout.addSubview(v1)

在这里插入图片描述

颜色统一管理(图片相同)

在这里插入图片描述

引入动态颜色生成库

pod 'DynamicColor'

实现

//
//  SuperUIColorExtension.swift
//  ExDemoApp
//
//  扩展系统颜色
//import Foundation
import DynamicColorextension UIColor {/// 背景颜色 (浅色)static var bgLightColor: UIColor{return DynamicColor(hex: 0xfafafa)}/// 背景颜色 (深色)static var bgDarkColor: UIColor{return DynamicColor(hex: 0x000000)}/// 背景颜色static var bgColor: UIColor{return .initColor(normal: bgLightColor, dark: bgDarkColor)}/// 红色static var red: UIColor{return DynamicColor(hex: 0xff0000)}/// 绿色static var green: UIColor{return DynamicColor(hex: 0x00ff00)}/// 蓝色static var blue: UIColor{return DynamicColor(hex: 0x00ffff)}/// 深浅颜色随系统切换static func initColor(normal: UIColor, dark: UIColor) -> UIColor{if #available(iOS 13.0, *) {return UIColor{ traitCollection -> UIColor inreturn traitCollection.userInterfaceStyle == .dark ? dark : normal}}else{return normal}}}
//
//  ViewController.swift
//  ExDemoApp
//import UIKit
import TangramKit
import DynamicColorclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = .bgColorlet horzLayout = TGLinearLayout(.horz)horzLayout.tg_gravity = TGGravity.horz.fillhorzLayout.backgroundColor = .grayhorzLayout.tg_width.equal(.fill)horzLayout.tg_height.equal(60)horzLayout.tg_bottom.equal(TGLayoutPos.tg_safeAreaMargin)view.addSubview(horzLayout)let v1 = QMUIButton()v1.setTitle("v1", for: .normal)v1.setTitleColor(.red, for: .normal)v1.tg_width.equal(.fill)v1.tg_height.equal(.fill)horzLayout.addSubview(v1)let v2 = QMUIButton()v2.setTitle("v2", for: .normal)v2.setTitleColor(.green, for: .normal)v2.tg_width.equal(.fill)v2.tg_height.equal(.fill)horzLayout.addSubview(v2)let v3 = QMUIButton()v3.setTitle("v3", for: .normal)v3.setTitleColor(.blue, for: .normal)v3.tg_width.equal(.fill)v3.tg_height.equal(.fill)horzLayout.addSubview(v3)}}

网络请求 Moya

允许http请求

在这里插入图片描述




NSAppTransportSecurityNSAllowsArbitraryLoads


配置请求地址

//
//  Config.swift
//  ExDemoApp
//import Foundationclass Config{/// 接口地址static let API_URL = "http://127.0.0.1:8080/";
}

引入网络请求框架

pod 'Moya'

使用请求

在这里插入图片描述

// 服务端
let http = require('http');http.createServer((req, res) => {res.writeHead(200, { 'Content-type': 'application/json' });if (req.url === '/api/getUserInfo' && req.method === 'POST') {let data = '';req.on('data', (chunk) => {data += chunk;});req.on('end', () => {console.log(JSON.stringify({code: 200, id: Math.random(), ...JSON.parse(data)}));res.end(JSON.stringify({code: 200, id: Math.random(), ...JSON.parse(data)}));});}
}).listen(8080);console.log('http://127.0.0.1:8080/');
//
//  ViewController.swift
//  ExDemoApp
//import UIKit
import TangramKit
import DynamicColor
import Moyaclass ViewController: UIViewController {var label: QMUILabel = QMUILabel()override func viewDidLoad() {super.viewDidLoad()view = TGRelativeLayout()view.backgroundColor = .bgColorlet button = QMUIButton()button.setTitle("请求", for: .normal)button.tg_width.equal(.wrap)button.tg_height.equal(.wrap)button.tg_centerX.equal(0)button.tg_centerY.equal(0)button.addTarget(self, action: #selector(handleClick(_ :)), for: .touchUpInside)view.addSubview(button)label.text = "暂无数据!"label.tg_width.equal(.wrap)label.tg_height.equal(.wrap)label.tg_centerX.equal(0)label.tg_centerY.equal(30)view.addSubview(label)}@objc func handleClick (_ sender: QMUIButton){let provider = MoyaProvider()provider.request(.getUserInfo(firstName: "Lee", lastName: "Prosper")) { result inswitch result {case let .success(moyaResponse):if moyaResponse.statusCode == 200 {let data: String = String(data: moyaResponse.data, encoding: .utf8)!self.label.text = dataprint(data)}case let .failure(error):print(error)}}}}/// 默认服务
enum DefaultService {case getUserInfo(firstName: String, lastName: String)
}extension DefaultService: TargetType {/// 请求地址var baseURL: URL { return URL(string: Config.API_URL)! }/// 接口地址var path: String {switch self {case .getUserInfo:return "/api/getUserInfo"}}/// 请求方式var method: Moya.Method {switch self {case .getUserInfo:return .post}}/// 请求参数var task: Task {switch self {case let .getUserInfo(firstName, lastName):return .requestParameters(parameters: ["first_name": firstName, "last_name": lastName], encoding: JSONEncoding.default)}}/// 请求头var headers: [String: String]? {let headers: Dictionary = [:]return headers}
}

网络请求 Moya/RxSwift

Moya/RxSwift 响应式编程,可以对数据在请求前做一些处理,如:provider.rx.request(.xxx()).filter{... in ...}.subscribe { ... }

引入RxSwift

# pod 'Moya'
pod 'Moya/RxSwift'pod 'NSObject+Rx'

使用

//  ViewController.swiftimport RxSwift
import NSObject_Rx@objc func handleClick (_ sender: QMUIButton){let provider = MoyaProvider()provider.rx.request(.getUserInfo(firstName: "Lee", lastName: "Prosper")).subscribe { event inswitch event {case let .success(response):if response.statusCode == 200 {let data: String = String(data: response.data, encoding: .utf8)!self.label.text = dataprint(data)}case let .failure(error):print(error)}}.disposed(by: rx.disposeBag) // 用于释放subscribe资源}

解析 json

在这里插入图片描述

pod 'HandyJSON'
//  ViewController.swiftimport Moya
import RxSwift
import NSObject_Rx
import HandyJSONclass UserInfo: HandyJSON {var code: Int!              // 不允许空var id: Double!             // 不允许空var first_name: String?     // 允许空var last_name: String?      // 允许空required init() {}
}let provider = MoyaProvider()
provider.rx.request(.getUserInfo(firstName: "Lee", lastName: "Prosper")).subscribe { event inswitch event {case let .success(response):if response.statusCode == 200 {let data: String = String(data: response.data, encoding: .utf8)!if let object = UserInfo.deserialize(from: data) {self.label.text = "\(object.code!) \n \(object.id!) \n \(object.first_name!) \n \(object.last_name!)"print(object.toJSONString(prettyPrint: true)!) // 转json字符串 - {"id":0.86519265844265569,"last_name":"Prosper","code":200,"first_name":"Lee"}}}case let .failure(error):print(error)}}.disposed(by: rx.disposeBag) // 用于释放subscribe资源

相关内容

热门资讯

编程安卓系统和鸿蒙主题,跨平台... 你有没有想过,手机的世界里,除了苹果的iOS和安卓的操作系统,还有个神秘的鸿蒙系统?今天,咱们就来聊...
哪个安卓机系统好用,探索安卓系... 你有没有想过,手机里的安卓系统就像是个大厨,不同的系统就像不同的烹饪手法,有的让你吃得津津有味,有的...
安卓如何控制苹果系统,从安卓到... 你知道吗?在这个科技飞速发展的时代,安卓和苹果两大操作系统之间的较量从未停歇。虽然它们各自有着忠实的...
安卓原生系统文件夹,安卓原生系... 你有没有发现,每次打开安卓手机,里面那些文件夹就像是一个个神秘的宝箱,里面藏着各种各样的宝贝?今天,...
基于安卓系统的游戏开发,从入门... 你有没有想过,为什么安卓手机上的游戏总是那么吸引人?是不是因为它们就像是你身边的好朋友,随时随地都能...
安卓系统怎样装驱动精灵,安卓系... 你那安卓设备是不是突然间有点儿不给力了?别急,今天就来手把手教你如何给安卓系统装上驱动精灵,让你的设...
如何本地安装安卓系统包,详细步... 你有没有想过,把安卓系统装在你的电脑上,是不是就像给电脑穿上了时尚的新衣?想象你可以在电脑上直接玩手...
安卓12卡刷系统教程,体验全新... 你有没有发现,你的安卓手机最近有点儿不给力了?运行速度慢得像蜗牛,是不是也想给它来个“换血大法”,让...
安卓系统无法打开swf文件,安... 最近是不是发现你的安卓手机有点儿不给力?打开SWF文件时,是不是总是出现“无法打开”的尴尬局面?别急...
鸿蒙系统依赖于安卓系统吗,独立... 你有没有想过,我们手机里的那个鸿蒙系统,它是不是真的完全独立于安卓系统呢?这个问题,估计不少手机控都...
适合安卓系统的图片软件,精选图... 手机里堆满了各种美美的照片,是不是觉得找起来有点头疼呢?别急,今天就来给你安利几款超级适合安卓系统的...
阴阳师安卓系统典藏,探寻阴阳师... 亲爱的阴阳师们,你是否在安卓系统上玩得如痴如醉,对那些精美的典藏式神们垂涎欲滴?今天,就让我带你深入...
安卓系统有碎片化缺点,系统优化... 你知道吗?在手机江湖里,安卓系统可是个响当当的大侠。它那开放、自由的个性,让无数手机厂商和开发者都为...
安卓4系统手机微信,功能解析与... 你有没有发现,现在市面上还有很多安卓4系统的手机在使用呢?尤其是那些喜欢微信的朋友们,这款手机简直就...
鸿蒙系统是安卓的盗版,从安卓“... 你知道吗?最近在科技圈里,关于鸿蒙系统的讨论可是热闹非凡呢!有人说是安卓的盗版,有人则认为这是华为的...
安卓系统怎么剪辑音乐,轻松打造... 你是不是也和我一样,手机里存了超多好听的歌,但是有时候想给它们来个变身,变成一段专属的旋律呢?别急,...
怎么把安卓手机系统变为pc系统... 你有没有想过,把你的安卓手机变成一台PC呢?听起来是不是有点酷炫?想象你可以在手机上玩电脑游戏,或者...
手机怎么装安卓11系统,手机安... 你有没有想过,让你的手机也来个“青春焕发”,升级一下系统呢?没错,就是安卓11系统!这个新系统不仅带...
安卓系统如何拼网络,构建高效连... 你有没有想过,你的安卓手机是怎么和网络“谈恋爱”的呢?没错,就是拼网络!今天,就让我带你一探究竟,看...
安卓系统怎么看小说,轻松畅享电... 你有没有发现,手机里装了那么多应用,最离不开的竟然是那个小小的小说阅读器?没错,就是安卓系统上的小说...