iOS(一):Swift纯代码模式iOS开发入门教程

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

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 frameworks
  use_frameworks!

  # Pods for ExDemoApp
  
  pod 'SnapKit'

end

安装

$ pod install

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

//
//  ViewController.swift
//  ExDemoApp
//
//  Created by ProsperLee on 2023/2/20.
//

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        let label: UILabel = UILabel()
        view.addSubview(label)
        label.text = "Hello"
        label.textColor = .red
        label.snp.makeConstraints {
    
     make in
            make.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 frameworks
  use_frameworks!

  # Pods for ExDemoApp
  
  pod 'SnapKit'
  
  pod 'QMUIKit'

end
$ pod install

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

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

测试桥接是否成功

在这里插入图片描述

//
//  ViewController.swift
//  ExDemoApp
//
//  Created by ProsperLee on 2023/2/20.
//

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        let button = QMUIButton()
        button.adjustsButtonWhenHighlighted = true
        button.setTitle("按钮", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = UIColor.tintColor;
        button.highlightedBackgroundColor = UIColor.tintColor;
        button.layer.cornerRadius = 4
        view.addSubview(button)
        button.snp.makeConstraints {
    
     make in
            make.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 UIKit

class 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 SnapKit

class 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 in
            make.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 SnapKit

class 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 = .white
        
        addSubview(leftIcon)
        addSubview(title)
        addSubview(rightIcon)
        
    }
    
    // 当view被首次添加进父级视图的时候调用
    override func didMoveToSuperview() {
    
    
        super.didMoveToSuperview()
        
        leftIcon.snp.makeConstraints{
    
    make in
            make.width.equalTo(32)
            make.height.equalTo(32)
            make.centerY.equalToSuperview()
            make.left.equalToSuperview().offset(16)
        }
        
        title.snp.makeConstraints{
    
    make in
            make.centerY.equalToSuperview()
            make.left.equalTo(leftIcon.snp.right).offset(10)
        }
        
        rightIcon.snp.makeConstraints{
    
    make in
            make.width.equalTo(20)
            make.height.equalTo(20)
            make.centerY.equalToSuperview()
            make.right.equalToSuperview().offset(-16)
        }
        
    }
    
}

使用组件并配置点击事件

//
//  SettingController.swift
//  设置界面
//

import UIKit

class 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 in
            make.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.strings
  ExDemoApp
*/


HomeMenuText = "首页";
//
//  ViewController.swift
//  ExDemoApp
//

import UIKit
import TangramKit

class 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.fill
        horzLayout.backgroundColor = UIColor.orange
        horzLayout.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 = .red
        v1.textAlignment = .center;
        v1.tg_width.equal(.fill)
        v1.tg_height.equal(.fill)
        horzLayout.addSubview(v1)
        
        let v2 = QMUILabel();
        v2.text = "v2"
        v2.backgroundColor = .green
        v2.textAlignment = .center;
        v2.tg_width.equal(.fill)
        v2.tg_height.equal(.fill)
        horzLayout.addSubview(v2)
        
        let v3 = QMUILabel();
        v3.text = "v3"
        v3.backgroundColor = .blue
        v3.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.strings
  ExDemoApp
*/

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 DynamicColor

extension 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 in
                return traitCollection.userInterfaceStyle == .dark ? dark : normal
            }
        }else{
    
    
            return normal
        }
    }
    
}
//
//  ViewController.swift
//  ExDemoApp
//

import UIKit
import TangramKit
import DynamicColor

class ViewController: UIViewController {
    
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        view.backgroundColor = .bgColor
        
        let horzLayout = TGLinearLayout(.horz)
        horzLayout.tg_gravity = TGGravity.horz.fill
        horzLayout.backgroundColor = .gray
        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.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请求

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
</dict>
</plist>

配置请求地址

//
//  Config.swift
//  ExDemoApp
//

import Foundation

class 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 Moya

class ViewController: UIViewController {
    
    
    
    var label: QMUILabel = QMUILabel()
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        view = TGRelativeLayout()
        view.backgroundColor = .bgColor
        
        let 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<DefaultService>()
        provider.request(.getUserInfo(firstName: "Lee", lastName: "Prosper")) {
    
     result in
            switch result {
    
    
            case let .success(moyaResponse):
                if moyaResponse.statusCode == 200 {
    
    
                    let data: String = String(data: moyaResponse.data, encoding: .utf8)!
                    self.label.text = data
                    print(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<String, String> = [:]
        return headers
    }
}

网络请求 Moya/RxSwift

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

引入RxSwift

# pod 'Moya'
pod 'Moya/RxSwift'

pod 'NSObject+Rx'

使用

//  ViewController.swift

import RxSwift
import NSObject_Rx


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

解析 json

在这里插入图片描述

pod 'HandyJSON'
//  ViewController.swift

import Moya
import RxSwift
import NSObject_Rx
import HandyJSON


class UserInfo: HandyJSON {
    
    
    var code: Int!              // 不允许空
    var id: Double!             // 不允许空
    var first_name: String?     // 允许空
    var last_name: String?      // 允许空
    
    required init() {
    
    }
}


let provider = MoyaProvider<DefaultService>()
provider.rx.request(.getUserInfo(firstName: "Lee", lastName: "Prosper"))
    .subscribe {
    
     event in
        switch 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资源

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/129368805