前言:一直想尝试做个mac端的东西,今天有机会了,在B站学习的音乐APP全栈,于是就想到了后台如果用mac端做如何,边学习边搭建
1、技术选择,采用Swift+MVVM+RxSwift结构搭建整个项目
Swift:这个当代苹果端开发,不会就废废了。
MVVM:一直在用,但一直不用不到精髓,多多练习,欢迎指教。
RxSwift:基本上Swift的MVVM大概率离不开RxSwift。
2、UI搭建选择
这个我单独拿出来说是因为,SwiftUI我真不会,只好使用storyboard搭建。
3、项目初始化
注意:在使用Xcode 14版本时,通过cocoapods安装第三方框架要把cocoapods更新到最新的版本,ruby环境也更新到最新(别问我为什么这么做,全是眼泪)
引入的库
这里使用HandyJSON进行解析,这个是我用过最傻瓜式的解析方式,考虑的最少,别的框架我也用过,但是如果不确定服务端返回到底有啥东西,就可能各种崩溃。HandyJSON就可以少操心。
4、上代码
先展示一下基本的项目结构
Network层
BaseAPIProtocol.swift
import Foundation
import Moya
protocol BaseAPIProtocol: TargetType {
var timeout: Double { get }
}
extension BaseAPIProtocol {
var baseURL: URL {
return URL(string: NetworkConfig.baseURL)!
}
var method: Moya.Method {
return .post
}
var headers: [String : String]? {
return ["":""]
}
var validationType: ValidationType {
return .successCodes
}
var timeout: Double {
return 30.0
}
}
Network层
BaseAPIProtocol.swift
import Foundation
import Moya
struct NetworkConfig {
static var baseURL: String {
return "http://localhost:88/"
}
static let contentType = "application/json"
}
Api.swift
import Foundation
import Moya
import Alamofire
enum API {
case siginIn(username: String, password: String)
}
extension API: BaseAPIProtocol {
var path: String {
switch self {
case .siginIn:
return "users/"
}
}
var method: Moya.Method {
switch self {
case .siginIn:
return .get
}
}
var task: Moya.Task {
var parameters: [String : Any] = [:]
switch self {
case .siginIn(let username, let password):
parameters = ["username": username, "password": password] as [String : Any]
return .requestParameters(parameters: parameters, encoding: URLEncoding.default)
}
}
}
登录部分
我的登录部分叫Sigin in,看到很多国际大厂这么叫,所以我打算国际化一点,嘿嘿。
先搭起一个简单的功能模块,测试一下能否请求到之前简单搭起后端的功能。
UserinfoModel.swift
import Foundation
import HandyJSON
struct UserinfoModel: HandyJSON {
var id: String = ""
var username: String = ""
var nickname: String = ""
var gender: String = ""
var email: String = ""
var phone: String = ""
}
SigninViewModel.swift
import Foundation
import Moya
import RxSwift
import RxCocoa
// 先订阅,再发送
class SigininViewModel: NSObject {
let signinSubject = PublishSubject<UserinfoModel>()
let disbg = DisposeBag()
lazy var userInfo: UserinfoModel = UserinfoModel()
func getUserInfo(username: String, password: String) -> Void {
let signinProvider = MoyaProvider<API>()
signinProvider.rx.request(.siginIn(username: username, password: password)).subscribe { [self] resopnse in
print("----响应为\(resopnse)--\(try! resopnse.mapString())")
if let userinfo: UserinfoModel = UserinfoModel.deserialize(from: try! resopnse.mapString()) {
signinSubject.onNext(userinfo)
} else {
print("有空值\(resopnse)--\(try! resopnse.mapString())")
}
} onFailure: { error in
print(error)
}
onDisposed: {
}.disposed(by: disbg)
}
}
SigninViewController.swift
import Cocoa
import RxSwift
class SigninViewController: NSViewController {
lazy var signinViewModel: SigininViewModel = SigininViewModel()
let disbg: DisposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
signIn(username: "a", password: "b")
// Do view setup here.
}
// 先订阅,再发送,rx使用要记牢
func signIn(username: String, password: String) -> Void {
signinViewModel.signinSubject.subscribe { [weak self] userInfo in
self?.signinViewModel.userInfo = userInfo
}.disposed(by: disbg)
signinViewModel.getUserInfo(username: username, password: password)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
5、调试
调试一下看看是否成功
啊这。。。
搜素了一下(还得是谷歌)确定是沙盒问题,好像不是Xcode 14的问题,之前的版本好像也有这个问题,但是我没碰到。
我勾选了这两个就OK了,可以请求到东西了