一个简单的swift项目

2019-04-18  本文已影响0人  鼬殿

简述:swift语法看的差不多后,就写了个简单的项目架构(其中涉及的语法还是很多的),一写起来,就感觉swift赏心悦目有木,虽说有些地方很晦涩,但是熟悉起来就好了,建议学swift还是先研究语法,这样上手会轻松很多,下面上代码

关于代码里面涉及的语法就不啰嗦了,大家根据自己所学对照验证

LZ用的是读取info.plist方式获取tabBarItem配置信息

屏幕快照 2019-04-18 下午4.15.29.png
class NJF_TabBarViewController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        
        let itemUrl: String? = Bundle.main.path(forResource: TabBarItemInfo, ofType: nil)
        if itemUrl == nil {return}
        let dictItemArr: NSArray? = NSArray(contentsOfFile: itemUrl!)
        if dictItemArr == nil {return}
        dictItemArr?.enumerateObjects({ (obj, idx, stop) in
            //校验
            guard let itemDict = obj  as? [String : NSObject] else {return}
            let clsN: String = itemDict["vc"] as! String
            let cls: AnyClass? = classFromCls(clsN)
            if cls == nil {return}
            let vcCls = cls as! UIViewController.Type
            let vc = vcCls.init()
            addChildVC(vc, itemTitle: itemDict["title"] as! NSString, imageN: itemDict["normalImgeName"] as! NSString, selImageN: itemDict["selImgeName"] as! NSString)
        })
    }
}

extension NJF_TabBarViewController {
    fileprivate func addChildVC(_ vc: UIViewController, itemTitle: NSString, imageN: NSString, selImageN: NSString) {
        var image : UIImage = UIImage(named: imageN as String)!
        var selImage : UIImage = UIImage(named: selImageN as String)!
        image = image.withRenderingMode(UIImage.RenderingMode.alwaysOriginal);
        selImage = selImage.withRenderingMode(UIImage.RenderingMode.alwaysOriginal);
        vc.tabBarItem = UITabBarItem.init(title: itemTitle as String, image: image, selectedImage: selImage)
        //改变字体颜色
        vc.tabBarItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.init(r: 255, g: 211, b: 59)], for:.selected)
        vc.title = itemTitle as String
        let nav = NJF_NavigationViewController(rootViewController: vc)
        addChild(nav)
    }
}
class NJF_NavigationViewController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        initializeSet()
    }
    
    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        //隐藏底部tabBar
        if viewControllers.count > 0 {
            viewController.hidesBottomBarWhenPushed = true
            viewController.navigationItem.leftBarButtonItem = UIBarButtonItem.init(imageName: "nav_btn_back_white", higImageName: "", size: .zero, target: self, action: #selector(navBack))
        }
        super.pushViewController(viewController, animated: animated)
    }
    
    //改变状态栏颜色
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    
    //退出键盘
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    //返回
    @objc func navBack() {
        self.popViewController(animated: true)
    }
}

extension NJF_NavigationViewController {
    fileprivate func initializeSet() {
        //设置字体大小和颜色
        UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white,NSAttributedString.Key.font : UIFont.systemFont(ofSize: 18)]
        //设置背景色
        UINavigationBar.appearance().barTintColor = UIColor.orange
        //设置半透明
        UINavigationBar.appearance().isTranslucent = false
        // 4.设置导航栏背景图片
        UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
        // 5.设置导航栏阴影图片
        UINavigationBar.appearance().shadowImage = UIImage()
    }
}
/************************application相关*******************/
/// 当前app版本号
let KAppCurrentVersion = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
/// 当前app的build号
let KAppBuildVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
/// 获取设备当前系统
let KSystemVersion = UIDevice.current.systemVersion

/************************屏幕坐标、尺寸相关*******************/

let IS_IPHONE4  = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:640,height:960), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONE5  = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:640,height:1336), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONE6  = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:750,height:1334), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONE6P  = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:1242,height:2208), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONE6PBigMode = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:1125,height:2001), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONEX = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:1125,height:2436), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONEXR = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:828,height:1792), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONEXSM  = UIScreen.instancesRespond(to:#selector(getter: UIScreen.main.currentMode)) ? __CGSizeEqualToSize(CGSize(width:1242,height:2688), (UIScreen.main.currentMode?.size)!) : false
let IS_IPHONEXAll = (IS_IPHONEX||IS_IPHONEXR||IS_IPHONEXSM)

//适配参数
let suitParm:CGFloat = ((IS_IPHONE6||IS_IPHONEXR||IS_IPHONEXSM) ? 1.12 : (IS_IPHONE6 ? 1.0 : (IS_IPHONE6PBigMode ? 1.01 : (IS_IPHONEX ? 1.0 : 0.85))))

let KscreenWidth = UIScreen.main.bounds.width
let KscreenHeight = UIScreen.main.bounds.height

let kNavigationBarHeight = 44.0
let kStatusBarHeight = IS_IPHONEXAll ? 44.0 : 20.0
let kSafeAreaTopHeight = IS_IPHONEXAll ? 88.0 : 64.0
let kSafeAreaBottomHeight = IS_IPHONEXAll ? 34.0 : 0
let kTabbarHeight = 49.0
extension UIColor {
    convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
        self.init(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1.0)
    }
    convenience init(rgb: UInt) {
        self.init(
            red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
            blue: CGFloat(rgb & 0x0000FF) / 255.0,
            alpha: CGFloat(1.0)
        )
    }
    class func andomColor() -> UIColor {
        return UIColor(r: CGFloat(arc4random_uniform(256)), g: CGFloat(arc4random_uniform(256)), b: CGFloat(arc4random_uniform(256)))
    }
}

lz把Moya的二次封装分了三个类别(实际项目中还应该在封装一层):
1.基础Moya的API部分->MoyaApi
2.url配置类->MoyaApiConfig
3.工具类->MoyaManager

enum MoyaAPI {
    /********************登录模块****************/
    case register(account:String, password:String)//注册
}

extension MoyaAPI: TargetType {
    var baseURL: URL {
        return URL.init(string: Moya_BaseUrl)!
    }
    
    var path: String {
        switch self {
        case .register:
            return LoginModule_Register
        }
    }
    
    var method: Moya.Method {
        switch self {
        case .register:
            return .post
//        default:
//            return .get
        }
    }
    
    ///这个是做单元测试模拟的数据,必须要实现,只在单元测试文件中有作用
    var sampleData: Data {
         return "".data(using: String.Encoding.utf8)!
    }
    
    var task: Task {
        switch self {
        case let .register(account, password):
            return .requestParameters(parameters: ["account":account, "password":password], encoding: JSONEncoding.default)
        }
    }
    
    var headers: [String : String]? {
//        return ["Content-Type":"application/json"]
        return nil
    }
    
}
///baseUrl

let Moya_BaseUrl = "https://www.xxx.com"

///path

/***********************登录模块*********************/

let LoginModule_Register = "/login/register"
/// 超时时长
private var requestTimeOut: Double = 15
///成功数据的回调
typealias successCallback = ((Any) -> (Void))
///失败的回调
typealias failedCallback = ((String) -> (Void))

/// endpointClosure用来构建Endpoint
private let myEndpointClosure = { (target: MoyaAPI) -> Endpoint in
    let url = target.baseURL.absoluteString + target.path
    
    var endpoint = Endpoint(
        url: url,
        sampleResponseClosure: { .networkResponse(200, target.sampleData) },
        method: target.method,
        task: target.task,
        httpHeaderFields: target.headers
    )
//    requestTimeOut = 15 //按照项目需求针对单个API设置不同的超时时长
    return endpoint
}

///网络请求的设置
private let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
    do {
        var request = try endpoint.urlRequest()
        //设置请求时长
        request.timeoutInterval = requestTimeOut
        // 打印请求参数
        if let requestData = request.httpBody {
            print("\(request.url!)"+"\n"+"\(request.httpMethod ?? "")"+"发送参数"+"\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
        }else{
            print("\(request.url!)"+"\(String(describing: request.httpMethod))")
        }
        done(.success(request))
    } catch {
        done(.failure(MoyaError.underlying(error, nil)))
    }
}

/// NetworkActivityPlugin插件用来监听网络请求
private let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
    debugPrint("networkPlugin \(changeType)")
    //targetType 是当前请求的基本信息
    switch(changeType){
    case .began:
        print("开始请求网络")
    case .ended:
        print("结束")
    }
}

////网络请求发送的核心初始化方法,创建网络请求对象
let Provider = MoyaProvider<MoyaAPI>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)


func NetworkRequest(_ target: MoyaAPI, completion: @escaping successCallback, failed:failedCallback?){
    Provider.request(target) { (result) in
        switch result {
            
        case let .success(response):
            do {
                //转JSON
                let responseObject = try JSONSerialization.jsonObject(with: response.data)
                guard let dic = responseObject as? Dictionary<String, Any>, let _ = String(data: response.data, encoding: String.Encoding.utf8) else {
                    debugPrint("什么情况?不是json数据?????")
                    return
                }
                completion(dic)
            } catch {
                
            }
        case let .failure(error):
             failed!(error.localizedDescription)
        }
    }
}

代码就不一一看了,具体大家可以看看demo,结构还是很好的,后续如果涉及到一些复杂的在更新demo
demo

上一篇下一篇

猜你喜欢

热点阅读