美文网首页
一个简单的swift项目

一个简单的swift项目

作者: 鼬殿 | 来源:发表于2019-04-18 16:25 被阅读0次

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

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

    • UITabBarController

    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)
        }
    }
    
    • UINavigationController
    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)))
        }
    }
    
    • Moya的简单封装
      关于网络请求库,用Alamofire还是Moya看个人喜好了,个人比较喜欢Moya

    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

    相关文章

      网友评论

          本文标题:一个简单的swift项目

          本文链接:https://www.haomeiwen.com/subject/yrstgqtx.html