2023-10-28 設(shè)計(jì)模式理解

將要修改的全部都用類(lèi)然后調(diào)用的時(shí)候直接在manager里操作
如圖4個(gè)文件都是涉及到指標(biāo)的


811783580.png

class DHTechIndexManager: NSObject {
    
    
    /// 供指標(biāo)庫(kù)讀取文件
    /// - Parameter type: <#type description#>
    static func loadXML(type: DJQuoteMarketInfo.BCTechIndexType?) {
        
        if let targetPath = DHTechIndexPath.getTargetPath(for: type ?? .stock),
           let sortTechIndexPath = DHTechIndexPath.getSortTechIndexPath(for: type ?? .stock) {
            DHBaseTechIndexXmlEditor.loadXML(sortTechIndexPath: sortTechIndexPath, targetPath: targetPath) { str in
                
            }
        } else {
            DZPrint("Invalid BCTechIndexType")
        }
        
    }

    
    /// 保存常用指標(biāo)
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - saveData: <#saveData description#>
    ///   - finsehdHandler: <#finsehdHandler description#>
    static func saveNormalTechIndexImpl(type:DJQuoteMarketInfo.BCTechIndexType?,
                                        saveData: [BCTechIndexXMLTitleNode],
                                        finsehdHandler: @escaping (() -> Void)) {
        if let sortTechIndexPath = DHTechIndexPath.getSortTechIndexPath(for: type ?? .stock) {
            DHBaseTechIndexXmlEditor.saveNormalTechIndex(sortTechIndexPath: sortTechIndexPath, saveData: saveData, finsehdHandler: finsehdHandler)
        } else {
            DZPrint("Invalid BCTechIndexType")
        }
    }
    
    
    /// 獲取常用指標(biāo),優(yōu)先從文件中讀取,如果文件為空,則返回默認(rèn)指標(biāo)
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getNormalTechIndexImpl(type:DJQuoteMarketInfo.BCTechIndexType?,
                                       finshedHandler: @escaping ([BCTechIndexXMLTitleNode])->Void) {
        if let sortTechIndexPath = DHTechIndexPath.getSortTechIndexPath(for: type ?? .stock) {
            DHBaseTechIndexXmlEditor.getNormalTechIndex(type: type, sortTechIndexPath: sortTechIndexPath, finshedHandler: finshedHandler)
        } else {
            DZPrint("Invalid BCTechIndexType")
        }
    }

    
    
    /// 保存排序后的常用指(主副圖分組)
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - saveData: <#saveData description#>
    ///   - finsehdHandler: <#finsehdHandler description#>
    static func saveNormalTechIndexGroup(type:DJQuoteMarketInfo.BCTechIndexType?, saveData:(master:[BCTechIndexXMLTitleNode],figure:[BCTechIndexXMLTitleNode]),
                                         finsehdHandler:(()->Void)? = nil)
    {
        
        if let sortTechIndexPath = DHTechIndexPath.getSortTechIndexPath(for: type ?? .stock) {
            DHBaseTechIndexXmlEditor.saveNormalTechIndexGroup(sortTechIndexPath: sortTechIndexPath, saveData: saveData ,finsehdHandler: finsehdHandler)
        } else {
            DZPrint("Invalid BCTechIndexType")
        }
    }
    
    
    
    /// 獲取所有指標(biāo)(主圖附圖分組)
    /// - Parameters:
    ///   - sortTechIndexPath: <#sortTechIndexPath description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getNormalTechIndexGroup(type:DJQuoteMarketInfo.BCTechIndexType?,
                                        finshedHandler: @escaping ((master:[BCTechIndexXMLTitleNode],figure:[BCTechIndexXMLTitleNode]))->Void)
    {
        if let sortTechIndexPath = DHTechIndexPath.getSortTechIndexPath(for: type ?? .stock) {
            DHBaseTechIndexXmlEditor.getNormalTechIndexGroup(sortTechIndexPath: sortTechIndexPath, finshedHandler: finshedHandler)
        } else {
            DZPrint("Invalid BCTechIndexType")
        }
    }
    
    
    //MARK - 以下方法為老數(shù)據(jù)兼容方法
    
    /// 獲取常用指標(biāo)
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getNormalTechIndex(type:DJQuoteMarketInfo.MarketType?,
                                   finshedHandler: @escaping ([BCTechIndexXMLTitleNode])->Void) {
        if type == .CNStock {
            BCTechIndexXmlEditor.getNormalTechIndex { (obj) in
                finshedHandler(obj)
            }
        } else {
            BCTechIndexXmlEditor.Industry_getFilterTechIndex { (obj) in
                finshedHandler(obj)
            }
        }
    }
    
    
    
    /// 獲取指標(biāo)數(shù)據(jù)(按指標(biāo)類(lèi)型分類(lèi))
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getAllXMLTechIndexGroup( _ type:DJQuoteMarketInfo.BCTechIndexType?,
                                         finshedHandler : @escaping ([(groupName:String,indexData:[BCTechIndexXMLNodeItem])]?)->Void)
    {
    
        if type == .stock {
            DHBaseTechIndexXmlEditor.getAllXMLTechIndexGroup { (obj) in
                if var allContent = obj {
                    var updatedContent: [(groupName: String, indexData: [BCTechIndexXMLNodeItem])] = []
                    for content in allContent {
                        let groupName = content.groupName
                        var groupIndexData = content.indexData
                        //個(gè)股特色型不能有這3個(gè)特色指標(biāo)
                        if groupName == "特色型" {
                            let toRemove = ["情緒周期", "連板高度", "四季牛熊"]
                            groupIndexData = content.indexData.filter { !toRemove.contains($0.id) }
                        }
                        let updatedContentItem = (groupName: groupName, indexData: groupIndexData)
                        updatedContent.append(updatedContentItem)
                    }
                    allContent = updatedContent
                    finshedHandler(allContent)
                }
            }
        } else {
            DHBaseTechIndexXmlEditor.getAllXMLTechIndexGroup { (obj) in
                finshedHandler(obj)
            }
        }
    }
}

import UIKit

class DHTechIndexPath: NSObject {
    static let paths: [DJQuoteMarketInfo.BCTechIndexType: (targetPath: String, sortTechIndexPath: String)] = [
        .stock: (
            targetPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("bctechIndexxml.xml") ?? "",
            sortTechIndexPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("bcsortTechIndexPath.plist") ?? ""
        ),
        .industry: (
            targetPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("industry_bctechIndexxml.xml") ?? "",
            sortTechIndexPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("industry_bcsortTechIndexPath.plist") ?? ""
        ),
        .dpql: (
            targetPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("QL_bctechIndexxml.xml") ?? "",
            sortTechIndexPath: (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString?)?.appendingPathComponent("QL_bcsortTechIndexPath.plist") ?? ""
        )
    ]
    
    
    static func getTargetPath(for type: DJQuoteMarketInfo.BCTechIndexType) -> String? {
        return DHTechIndexPath.paths[type]?.targetPath
    }
    
    static func getSortTechIndexPath(for type: DJQuoteMarketInfo.BCTechIndexType) -> String? {
        return DHTechIndexPath.paths[type]?.sortTechIndexPath
    }
}

import UIKit

class DHDefaultTechIndex: NSObject {
    static let ownObj = DHDefaultTechIndex()
    //默認(rèn)指標(biāo)
    lazy var getDefaultTechIndex:[BCTechIndexXMLTitleNode] =
    {
        
        var retObj = [BCTechIndexXMLTitleNode]()
        retObj.append(BCTechIndexXMLTitleNode(id:"主力操盤(pán)", desc: "主力操盤(pán)"))
        retObj.append(BCTechIndexXMLTitleNode(id:"主力控盤(pán)", desc: "主力控盤(pán)"))
        retObj.append(BCTechIndexXMLTitleNode(id:"主力吸籌", desc: "主力吸籌"))
        //        retObj.append(BCTechIndexXMLTitleNode(id:"超短擒龍主", desc: "超短擒龍主"))
        //        retObj.append(BCTechIndexXMLTitleNode(id:"超短擒龍副", desc: "超短擒龍副"))
        retObj.append(BCTechIndexXMLTitleNode(id:"MA", desc: "MA"))
        retObj.append(BCTechIndexXMLTitleNode(id:"MACD", desc: "MACD"))
        retObj.append(BCTechIndexXMLTitleNode(id:"KDJ", desc: "KDJ"))
        retObj.append(BCTechIndexXMLTitleNode(id:"BOLL", desc: "BOLL"))
        retObj.append(BCTechIndexXMLTitleNode(id:"VOL", desc: "VOL"))
        
        return retObj
        
    }()
    
    
    //板塊指標(biāo)
    lazy var getIndustryTechIndex:[BCTechIndexXMLTitleNode] =
    {
        
        var retObj = [BCTechIndexXMLTitleNode]()
        retObj.append(BCTechIndexXMLTitleNode(id:"主力操盤(pán)", desc: "主力操盤(pán)"))
        retObj.append(BCTechIndexXMLTitleNode(id:"主力控盤(pán)", desc: "主力控盤(pán)"))
        retObj.append(BCTechIndexXMLTitleNode(id:"主力吸籌", desc: "主力吸籌"))
        //        retObj.append(BCTechIndexXMLTitleNode(id:"超短擒龍主", desc: "超短擒龍主"))
        //        retObj.append(BCTechIndexXMLTitleNode(id:"超短擒龍副", desc: "超短擒龍副"))
        retObj.append(BCTechIndexXMLTitleNode(id:"MA", desc: "MA"))
        retObj.append(BCTechIndexXMLTitleNode(id:"MACD", desc: "MACD"))
        retObj.append(BCTechIndexXMLTitleNode(id:"KDJ", desc: "KDJ"))
        retObj.append(BCTechIndexXMLTitleNode(id:"BOLL", desc: "BOLL"))
        retObj.append(BCTechIndexXMLTitleNode(id:"VOL", desc: "VOL"))
        retObj.append(BCTechIndexXMLTitleNode(id:"四季牛熊", desc: "四季牛熊"))
        retObj.append(BCTechIndexXMLTitleNode(id:"連板高度", desc: "連板高度"))
        retObj.append(BCTechIndexXMLTitleNode(id:"情緒周期", desc: "情緒周期"))
        
        return retObj
        
    }()
    
    
    //大盤(pán)擒龍指標(biāo)
    lazy var getQLTechIndex:[BCTechIndexXMLTitleNode] =
    {
        var retObj = [BCTechIndexXMLTitleNode]()
        //        retObj.append(BCTechIndexXMLTitleNode(id:"四季牛熊", desc: "四季牛熊"))
        //要判斷情緒周期指標(biāo)有沒(méi)有權(quán)限
        //zb1_fkld
        /*
         let zb1_fkld = DJPrivilageBusiness.isHaveData(funcType: .zb1_fkld)
         let ggQxzq = DJPrivilageBusiness.isHaveData(funcType: .ggQxzq)
         if zb1_fkld && ggQxzq{
         //兩個(gè)權(quán)限都有則一個(gè)都不顯示
         }else if (zb1_fkld == true && ggQxzq == false){
         //風(fēng)口輪動(dòng)還沒(méi)開(kāi)發(fā),也不添加
         }else if (zb1_fkld == false && ggQxzq == true){
         //只有情緒周期
         
         }else{
         //兩個(gè)權(quán)限都沒(méi)有
         }
         */
        let ggsjnx = DJPrivilageBusiness.isHaveData(funcType: .zb1_sjnx)
        if ggsjnx == true{
            retObj.append(BCTechIndexXMLTitleNode(id:"四季牛熊", desc: "四季牛熊"))
        }
        
        let ggQxzq = DJPrivilageBusiness.isHaveData(funcType: .ggQxzq)
        if ggQxzq == true{
            retObj.append(BCTechIndexXMLTitleNode(id:"情緒周期", desc: "情緒周期"))
        }
        
        let gglbgd = DJPrivilageBusiness.isHaveData(funcType: .zb1_lbgd)
        if gglbgd == true{
            retObj.append(BCTechIndexXMLTitleNode(id:"連板高度", desc: "連板高度"))
        }
        
        retObj.append(BCTechIndexXMLTitleNode(id:"MA", desc: "MA"))
        retObj.append(BCTechIndexXMLTitleNode(id:"MACD", desc: "MACD"))
        retObj.append(BCTechIndexXMLTitleNode(id:"KDJ", desc: "KDJ"))
        retObj.append(BCTechIndexXMLTitleNode(id:"BOLL", desc: "BOLL"))
        retObj.append(BCTechIndexXMLTitleNode(id:"VOL", desc: "VOL"))
        
        
        return retObj
    }()
    
}


import UIKit
class DHBaseTechIndexXmlEditor: NSObject {
    static let ownObj = DHBaseTechIndexXmlEditor()
    
    let loadXMLQueue = DispatchQueue(label: "DHBaseTechIndexXmlEditor.loadXMLQueue")
    
    
    //分組后的Content
    var techIndexContent:[(groupName:String,indexData:[BCTechIndexXMLNodeItem])]?
    
    //未分組的無(wú)序的Content
    var allTechIndexContent:[String:BCTechIndexXMLNodeItem]?
    

    
    private var orignXMLData:String?
    

    
    static var techIndexY = [String:[CGFloat?]?]()
    
    
    
    /// 查找指標(biāo)數(shù)據(jù)
    /// - Parameter techIndexID: <#techIndexID description#>
    /// - Returns: <#description#>
    static func findTechIndexData(techIndexID:String) -> BCTechIndexXMLNodeItem?
    {
        return ownObj.allTechIndexContent?[techIndexID]
    }
    
    
    /// 獲取指標(biāo)數(shù)據(jù)
    /// - Parameters:
    ///   - techIndexID: <#techIndexID description#>
    ///   - handler: <#handler description#>
    static func getTechIndexData(techIndexID:String, _ handler : @escaping (BCTechIndexXMLNodeItem?)->Void)
    {
        
        if let data = findTechIndexData(techIndexID: techIndexID)
        {
            DispatchQueue.main.async {
                handler(data)
            }
            return
        }
        else
        {
            
            self.ownObj.loadXMLQueue.async {
                if let data =  self.ownObj.techIndexContent
                {
                    for item in data
                    {
                        for subItem in item.indexData
                        {
                            if subItem.id == techIndexID
                            {
                                DispatchQueue.main.async {
                                    handler(subItem)
                                }
                                return
                            }
                        }
                    }
                }
                else
                {
                    DispatchQueue.main.async {
                        handler(nil)
                    }
                }
                
            }
            
        }
        
    }
    
    //默認(rèn)指標(biāo)
    lazy var getDefaultTechIndex:[BCTechIndexXMLTitleNode] =
    {
        return DHDefaultTechIndex.ownObj.getDefaultTechIndex
    }()
    
    //板塊指標(biāo)
    lazy var getIndustryTechIndex:[BCTechIndexXMLTitleNode] =
    {
        return DHDefaultTechIndex.ownObj.getIndustryTechIndex
    }()
    
    //大盤(pán)擒龍指標(biāo)
    func QL_getDefaultTechIndex() -> [BCTechIndexXMLTitleNode] {
        return DHDefaultTechIndex.ownObj.getQLTechIndex
    }
    
    
    //修改XML參數(shù)
    static func modifyXML(item:BCTechIndexXMLNodeItem,  finshedHandler: @escaping ()->Void)
    {
        
        ownObj.loadXMLQueue.async
        {
            
            //修改緩存中techIndexContent的參數(shù)數(shù)據(jù)
            if let index = ownObj.techIndexContent?.firstIndex(where: { (obj) -> Bool in
                
                return obj.groupName == item.groupName
            })
            {
                
                if let subIndex = ownObj.techIndexContent?[index].indexData.firstIndex(where: { (obj) -> Bool in
                    return item.id == obj.id
                })
                {
                    ownObj.techIndexContent?[index].indexData[subIndex] = item
                }
                
            }
            
            
            //修改整個(gè)XML數(shù)據(jù)
            if let xmlData = ownObj.orignXMLData
            {
                
                if  let obj = try? GDataXMLDocument(xmlString: xmlData)
                {
                    let domObj = obj.rootElement()
                    
                    
                    if let  findNode = try? domObj?.nodes(forXPath: "http://group1/group2/index") as? [GDataXMLNode],let params = item.params
                    {
                        if let contentNode = findNode
                        {
                            
                            for subItem in contentNode
                            {
                                
                                if let id = try? subItem.firstNode(forXPath: "@id").stringValue()
                                {
                                    if id == item.id
                                    {
                                        if let allElement = subItem.children()
                                        {
                                            //可以更改分量名稱(chēng)的指標(biāo),比如5日MA才睹,那么指標(biāo)描述名字為MA5,只是為了UI顯示直觀
                                            let canModifyContentName =  ["MA","EMA","SMA","PBX"].contains(id?.uppercased())
                                            
                                            //刪除原始參數(shù)元素
                                            for element in allElement
                                            {
                                                if element.name() == "param"
                                                {
                                                    (subItem as? GDataXMLElement)?.removeChild(element)
                                                }
                                            }
                                            
                                            //增加修改后的參數(shù)元素
                                            var contentString = ""
                                            for repaceItem in params
                                            {
                                                
                                                
                                                if  let name = repaceItem.name, let max = repaceItem.max ,let min = repaceItem.min , let value = repaceItem.value
                                                {
                                                    
                                                    let newElement = GDataXMLElement.element(withName: "param")
                                                    
                                                    let attributeName = GDataXMLNode.attribute(withName: "name", stringValue: name) as? GDataXMLNode
                                                    let attributeDesc = GDataXMLNode.attribute(withName: "desc", stringValue: "") as? GDataXMLNode
                                                    let attributeMin =  GDataXMLNode.attribute(withName: "min", stringValue: min) as? GDataXMLNode
                                                    let attributeMax = GDataXMLNode.attribute(withName: "max", stringValue: max) as? GDataXMLNode
                                                    let attributeValue = GDataXMLNode.attribute(withName: "default", stringValue:value) as? GDataXMLNode
                                                    let attributeStep = GDataXMLNode.attribute(withName: "step", stringValue: "0") as? GDataXMLNode
                                                    
                                                    
                                                    newElement?.addAttribute(attributeName)
                                                    newElement?.addAttribute(attributeDesc)
                                                    newElement?.addAttribute(attributeMin)
                                                    newElement?.addAttribute(attributeMax)
                                                    newElement?.addAttribute(attributeValue)
                                                    newElement?.addAttribute(attributeStep)
                                                    
                                                    (subItem as? GDataXMLElement)?.addChild(newElement)
                                                    
                                                    //一些均線名字通過(guò)參數(shù)而定 比如5日MA朱沃,那么指標(biāo)描述名字為MA5
                                                    if let nameValue = Float(value)
                                                    {
                                                        if id == "MA"
                                                        {
                                                            contentString = contentString + "MA\(Int(nameValue)):MA(CLOSE,\(name));"
                                                        }
                                                        else if id == "EMA"
                                                        {
                                                            contentString = contentString + "EMA\(Int(nameValue)):EMA(CLOSE,\(name));"
                                                        }
                                                        else if id == "SMA"
                                                        {
                                                            contentString = contentString + "SMA\(Int(nameValue)):SMA(CLOSE,\(name),1);"
                                                        }
                                                        else  if id == "PBX"
                                                        {
                                                            //PBX1:(EMA(CLOSE,M1)+MA(CLOSE,M1*2)+MA(CLOSE,M1*4))/3
                                                            contentString = contentString + "PBX\(Int(nameValue)):(EMA(CLOSE,\(name))+MA(CLOSE,\(name)*2)+MA(CLOSE,\(name)*4))/3;"
                                                        }
                                                    }
                                                    
                                                }
                                                
                                                
                                            }
                                            
                                            if canModifyContentName
                                            {
                                                //let newElement = GDataXMLElement.element(withName: "content")
                                                if  let contentAtr = try?subItem.firstNode(forXPath: "@content")
                                                {
                                                    (subItem as? GDataXMLElement)?.removeChild(contentAtr)
                                                }
                                                
                                                (subItem as? GDataXMLElement)?.addChild(GDataXMLNode.attribute(withName: "content", stringValue: contentString) as? GDataXMLNode)
                                                
                                            }
                                            
                                            
                                            saveXMLModifyedXMLData(xmlData: obj.xmlData())
                                            
                                            
                                            DispatchQueue.main.async {
                                                finshedHandler()
                                            }
                                            
                                            break
                                            
                                        }
                                        
                                    }
                                    
                                    
                                    
                                }
                            }
                            
                            
                            
                            
                        }
                    }
                    
                    
                }
                
                
            }
            
        }
        
    }
}

//MARK: - 文件存儲(chǔ)相關(guān)
extension DHBaseTechIndexXmlEditor
{
    
    //XML保存路徑
    static let targetPath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first as NSString?)?.appendingPathComponent("bctechIndexxml.xml")
    
    //XML初始路徑
    static let initPath =  Bundle.main.path(forResource: "sys_index", ofType: "xml")


    static let initXMLXRC32Key =   "initXMLXRC32Key"
    
    
    
    
    
    
    //供指標(biāo)庫(kù)讀取文件
    @objc static func loadXML(sortTechIndexPath: String,
                              targetPath: String?,
                              finshedHandler: @escaping (String?)->Void)
    {
        DHBaseTechIndexXmlEditor.ownObj.loadXMLQueue.async {
            
            var retObj:String?  = try? String(contentsOf: URL(fileURLWithPath: DHBaseTechIndexXmlEditor.initPath! ), encoding: .utf8)
            
            let sysIndexXMLCRC32 = DataEncryAndDecry.icrc32(with: retObj ?? "")
            let savedSysIndexXMLCRC32 =  Int(UserDefaults.standard.object(forKey: DHBaseTechIndexXmlEditor.initXMLXRC32Key) as? String ?? "-1")!
            
            if  savedSysIndexXMLCRC32 != sysIndexXMLCRC32
            {
                //刪除本地保存的指標(biāo)
                let fileManager = FileManager.default
                if fileManager.fileExists(atPath: sortTechIndexPath ?? "")
                {
                    if  let _ = try? fileManager.removeItem(atPath: sortTechIndexPath) {}
                }
                
                UserDefaults.standard.set(String(sysIndexXMLCRC32), forKey: DHBaseTechIndexXmlEditor.initXMLXRC32Key)
                
                UserDefaults.standard.synchronize()
            }
            else if let _targetPath = targetPath
            {
                if let retStr =   try? String(contentsOf: URL(fileURLWithPath: _targetPath ), encoding: .utf8)
                {
                    retObj = retStr
                }
            }
            
            DHBaseTechIndexXmlEditor.ownObj.orignXMLData = retObj
            DispatchQueue.main.async {
                finshedHandler(retObj)
            }
            parseXMLData { _ in
                
            }
            
            
//            DispatchQueue.main.async {
//
//                DHBaseTechIndexXmlEditor.ownObj.orignXMLData = retObj
//
//                finshedHandler(retObj)
//
//                DHBaseTechIndexXmlEditor.parseXMLData { _ in }
//
//
//
//            }
            
        }
    }
    
    
    
    /// 保存修改后的指標(biāo)
    /// - Parameter xmlData: <#xmlData description#>
     static func saveXMLModifyedXMLData(xmlData:Data)
    {
        guard let xmlString = String(data: xmlData, encoding: .utf8) else { return }
        
        DispatchQueue.global().async {
            BCTechIndexBusiness.updateIndexFormul(data: xmlString)
        }
        
        
        //更新數(shù)據(jù)
        if let _ = try? xmlString.write(to: URL(fileURLWithPath:targetPath!), atomically: true, encoding: .utf8)
        {
            
            
            ownObj.orignXMLData = xmlString
            
            parseXMLData { _ in
            }
            
        }
        
    }
    
    
    
    
    /// 解析指標(biāo)
    /// - Parameter finshedHandler: <#finshedHandler description#>
     static func parseXMLData( _ finshedHandler : @escaping ([(groupName:String,indexData:[BCTechIndexXMLNodeItem])]?)->Void)
    {
        
        ownObj.loadXMLQueue.async {
            
            if let xmlData = ownObj.orignXMLData
            {
                
                if  let obj = try? GDataXMLDocument(xmlString: xmlData)
                {
                    let domObj = obj.rootElement()
                    
                    
                    if let  findNode = try? domObj?.nodes(forXPath: "http://group1/group2") as? [GDataXMLNode]
                    {
                        if  let groupNode =   findNode
                        {
                            var techIndexContent = [(String,[BCTechIndexXMLNodeItem])]()
                            var allIndexConetent = [String:BCTechIndexXMLNodeItem]()
                            
                            for  item in  groupNode
                            {
                                
                                let groupName =  try! item.firstNode(forXPath: "@name").stringValue()
                                
                                
                                BCTechIndexXmlEditor.convertToTraditionalString(simpleString: groupName)
                                
                                var contentItem = (groupName!,[BCTechIndexXMLNodeItem]())
                                
                                let allContentNode = try! item.nodes(forXPath: "index") as! [GDataXMLNode]
                                for contentNode in allContentNode
                                {
                                    
                                    var item =  BCTechIndexXMLNodeItem()
                                    
                                    let indexID = try! contentNode.firstNode(forXPath: "@id").stringValue()
                                    BCTechIndexXmlEditor.convertToTraditionalString(simpleString: indexID)
                                    
                                    item.id = indexID
                                    
                                    item.groupName = groupName
                                    
                                    
                                    let inexName = try? contentNode.firstNode(forXPath: "@name").stringValue()
                                    item.name = inexName ?? ""
                                    BCTechIndexXmlEditor.convertToTraditionalString(simpleString: item.name)
                                    
                                    if let indexDesc = try? contentNode.firstNode(forXPath: "@desc").stringValue()
                                    {
                                        item.desc = indexDesc
                                        BCTechIndexXmlEditor.convertToTraditionalString(simpleString: item.desc)
                                    }
                                    
                                    if let help = try? contentNode.firstNode(forXPath: "@help").stringValue()
                                    {
                                        item.help = help
                                        BCTechIndexXmlEditor.convertToTraditionalString(simpleString: item.help)
                                    }
                                    
                                    if let flag = try? contentNode.firstNode(forXPath: "@flag").stringValue() ?? "0"
                                    {
                                        item.isMaster =  0x00100000 & (Int(flag) ?? 0) != 0
                                    }
                                    
                                    if let content = try? contentNode.firstNode(forXPath: "@content").stringValue()
                                    {
                                        item.content = content
                                        BCTechIndexXmlEditor.convertToTraditionalString(simpleString: item.content)
                                        print("content = \(content?.description)\n")
                                        //                                        print("")
                                        //                                        item.help = help
                                        //                                        DHBaseTechIndexXmlEditor.convertToTraditionalString(simpleString: item.help)
                                    }
                                    
                                    //解析默認(rèn)參數(shù)
                                    if let params = try? contentNode.nodes(forXPath: "defaultparam")
                                    {
                                        
                                        if params.count > 0
                                        {
                                            item.defaultparams = [(name:String?,value:String?,max:String?,min:String?)]()
                                            
                                            for paramNode in params
                                            {
                                                if let paramName = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@name").stringValue() ,  let paramValue = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@default").stringValue(),let max = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@max").stringValue(),let min = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@min").stringValue()
                                                {
                                                    item.defaultparams?.append((paramName,paramValue,max,min))
                                                }
                                            }
                                        }
                                        else
                                        {
                                            item.defaultparams = nil
                                        }
                                        
                                    }
                                    
                                    
                                    //解析參數(shù)
                                    if let params = try? contentNode.nodes(forXPath: "param")
                                    {
                                        item.params = [(name:String?,value:String?,max:String?,min:String?)]()
                                        
                                        let bAddDefaultParam =  item.defaultparams == nil
                                        if bAddDefaultParam
                                        {
                                            item.defaultparams = [(name:String?,value:String?,max:String?,min:String?)]()
                                            
                                        }
                                        for paramNode in params
                                        {
                                            if let paramName = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@name").stringValue() ,  let paramValue = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@default").stringValue(),let max = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@max").stringValue(),let min = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@min").stringValue()
                                            {
                                                item.params?.append((paramName,paramValue,max,min))
                                                
                                                if bAddDefaultParam
                                                {
                                                    item.defaultparams?.append((paramName,paramValue,max,min))
                                                }
                                                
                                            }
                                        }
                                    }
                                    
                                    
                                    
                                    
                                    //解析y
                                    if let params = try? contentNode.nodes(forXPath: "line")
                                    {
                                        item.Y = [CGFloat?]()
                                        
                                        for paramNode in params
                                        {
                                            
                                            if let y = try?  (paramNode as? GDataXMLNode)?.firstNode(forXPath: "@y").stringValue()
                                            {
                                                if let _y  = y
                                                {
                                                    item.Y?.append(CGFloat(Double(_y)!))
                                                }
                                                
                                            }
                                        }
                                    }
                                    
                                    contentItem.1.append(item)
                                    techIndexY[item.id] = item.Y
                                    allIndexConetent.updateValue(item, forKey: item.id)
                                    
                                    
                                }
                                
                                techIndexContent.append(contentItem)
                                
                                
                            }
                            
                            ownObj.techIndexContent = techIndexContent
                            ownObj.allTechIndexContent = allIndexConetent
                            finshedHandler(ownObj.techIndexContent)
                            
                            
                            
                            
                        }
                    }
                }
            }
            
            
        }
        
        
        
    }
    
    
    
    /// 獲取指標(biāo)數(shù)據(jù)(按指標(biāo)類(lèi)型分類(lèi))
    /// - Parameter finshedHandler: <#finshedHandler description#>
    static func getAllXMLTechIndexGroup( _ finshedHandler : @escaping ([(groupName:String,indexData:[BCTechIndexXMLNodeItem])]?)->Void)
    {
        
        if ownObj.techIndexContent?.count != 0 && ownObj.techIndexContent != nil
        {
            finshedHandler(ownObj.techIndexContent)
        }
        else
        {
            parseXMLData { (obj) in
                
                DispatchQueue.main.async {
                    
                    finshedHandler(obj)
                }
                
            }
        }
    }
    
   
    
    
    
    /// 保存排序后的常用指(主副圖分組)
    /// - Parameters:
    ///   - sortTechIndexPath: <#sortTechIndexPath description#>
    ///   - saveData: <#saveData description#>
    ///   - finsehdHandler: <#finsehdHandler description#>
    static func saveNormalTechIndexGroup(sortTechIndexPath:String,
                                         saveData:(master:[BCTechIndexXMLTitleNode],figure:[BCTechIndexXMLTitleNode]),
                                         finsehdHandler:(()->Void)? = nil)
    {
        DHBaseTechIndexXmlEditor.ownObj.loadXMLQueue.async {
            
            
            let masterMap = saveData.master.map({ (obj) -> [String:String?] in
                
                return [obj.id:obj.desc]
            })
            
            let figureMap = saveData.figure.map({ (obj) -> [String:String?]  in
                
                return [obj.id:obj.desc]
            })
            
            ([masterMap,figureMap] as NSArray).write(to: URL(fileURLWithPath: sortTechIndexPath), atomically: true)
            
            finsehdHandler?()
        }
        
    }
    
    
    
    
    /// 保存常用指標(biāo)
    /// - Parameters:
    ///   - sortTechIndexPath: <#sortTechIndexPath description#>
    ///   - saveData: <#saveData description#>
    ///   - finsehdHandler: <#finsehdHandler description#>
    static func saveNormalTechIndex(sortTechIndexPath:String,
                                    saveData:[BCTechIndexXMLTitleNode],
                                    finsehdHandler:(()->Void)? = nil)
    {
        DHBaseTechIndexXmlEditor.ownObj.loadXMLQueue.async {
            
            
            let masterMap = saveData.compactMap({ (obj) -> [String:String?] in
                
                return [obj.id:obj.desc]
            })
            
            (masterMap as NSArray).write(to: URL(fileURLWithPath: sortTechIndexPath), atomically: true)
            
            finsehdHandler?()
        }
        
    }
    
    
    

    
    /// 獲取常用指標(biāo),優(yōu)先從文件中讀取培廓,如果文件為空罗晕,則返回默認(rèn)指標(biāo)
    /// - Parameters:
    ///   - type: <#type description#>
    ///   - sortTechIndexPath: <#sortTechIndexPath description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getNormalTechIndex(type:DJQuoteMarketInfo.BCTechIndexType?,
                                   sortTechIndexPath:String,
                                   finshedHandler: @escaping ([BCTechIndexXMLTitleNode])->Void)
    {
        
//        DHBaseTechIndexXmlEditor.ownObj.loadXMLQueue.async
//        {
            
            
            var retObj = [BCTechIndexXMLTitleNode]()
            
            //如果本地保存了就從本地拿
            let arr =  NSArray(contentsOf: URL(fileURLWithPath: sortTechIndexPath))
            if (arr?.count ?? 0) != 0
            {
                if let data =  arr as? [[String:String?]]
                {
                    let _retObj = data.map({ obj -> BCTechIndexXMLTitleNode in
                        
                        return BCTechIndexXMLTitleNode(id:  obj.keys.first, desc: obj.values.first as? String)
                    })
                    retObj.append(contentsOf: _retObj)
                }
                
                
                finshedHandler(retObj)
                
                
                return
            }
            
            if type == .stock {
                retObj.append(contentsOf: DHBaseTechIndexXmlEditor.ownObj.getDefaultTechIndex)
            } else if type == .dpql {
                retObj.append(contentsOf: DHBaseTechIndexXmlEditor.ownObj.QL_getDefaultTechIndex())
            } else if type == .industry {
                retObj.append(contentsOf: DHBaseTechIndexXmlEditor.ownObj.getIndustryTechIndex)
            }
        
            
            
            //保存排序指標(biāo)
            DHBaseTechIndexXmlEditor.saveNormalTechIndex(sortTechIndexPath: sortTechIndexPath, saveData: retObj)
            
            
            //這里并生成
            finshedHandler(retObj)
            
            
//        }
        
        
    }
    
    
    
    /// 獲取所有指標(biāo)(主圖附圖分組)
    /// - Parameters:
    ///   - sortTechIndexPath: <#sortTechIndexPath description#>
    ///   - finshedHandler: <#finshedHandler description#>
    static func getNormalTechIndexGroup(sortTechIndexPath: String,
                                        finshedHandler: @escaping((master:[BCTechIndexXMLTitleNode],figure:[BCTechIndexXMLTitleNode]))->Void)
    {
        
        
        ownObj.loadXMLQueue.async
        {
            
            
            var retObj:(master:[BCTechIndexXMLTitleNode],figure:[BCTechIndexXMLTitleNode]) = ([BCTechIndexXMLTitleNode](),[BCTechIndexXMLTitleNode]())
            
            //如果本地保存了就從本地拿
            let arr =  NSArray(contentsOf: URL(fileURLWithPath: sortTechIndexPath))
            if (arr?.count ?? 0) != 0
            {
                if let masrterData = arr?.firstObject as? [[String:String?]]
                {
                    let _retObj = masrterData.map({ obj -> BCTechIndexXMLTitleNode in
                        
                        return BCTechIndexXMLTitleNode(id:  obj.keys.first, desc: obj.values.first as? String)
                    })
                    retObj.master.append(contentsOf: _retObj)
                }
                
                if let figureData = arr?.lastObject as? [[String:String?]]
                {
                    let _retObj = figureData.map({ obj -> BCTechIndexXMLTitleNode in
                        
                        return BCTechIndexXMLTitleNode(id:  obj.keys.first, desc: obj.values.first as? String)
                    })
                    
                    retObj.figure.append(contentsOf: _retObj)
                    
                }
                
                
                finshedHandler(retObj)
                
                
                return
            }
            
            //這里并生成
            finshedHandler(retObj)
            
        }
        
        
        
        
        
    }
    
    
    
    
    
    
}

extension DJQuoteMarketInfo
{
    enum BCTechIndexType: Int {
        /// 未知類(lèi)型,初始值0
        case unknown = 0
        /// 個(gè)股
        case stock = 1
        /// 板塊
        case industry = 2
        /// 大盤(pán)擒龍
        case dpql = 3
        /// 所有類(lèi)型
        case all = 4
    }

    
}

DHTechIndexManager負(fù)責(zé)給外部調(diào)用脆贵,外部想要什么業(yè)務(wù),只需要傳類(lèi)型或數(shù)據(jù)即可
DHTechIndexPath 負(fù)責(zé)根據(jù)類(lèi)型去取本地的指標(biāo)緩存路徑
DHDefaultTechIndex 負(fù)責(zé)默認(rèn)的指標(biāo)名字
DHBaseTechIndexXmlEditor 負(fù)責(zé)指標(biāo)業(yè)務(wù)的具體實(shí)現(xiàn)
DJQuoteMarketInfo 負(fù)責(zé)指標(biāo)類(lèi)型

總的來(lái)說(shuō)就是將一系列功能拆分成一個(gè)個(gè)的模塊起暮,有點(diǎn)類(lèi)似于構(gòu)造者模式卖氨。改的話(huà)只需要改一個(gè)地方,不會(huì)影響到其他地方,做到了對(duì)外擴(kuò)展對(duì)修改關(guān)閉筒捺!
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柏腻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子系吭,更是在濱河造成了極大的恐慌五嫂,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件村斟,死亡現(xiàn)場(chǎng)離奇詭異贫导,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蟆盹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)孩灯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人逾滥,你說(shuō)我怎么就攤上這事峰档。” “怎么了寨昙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵讥巡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我舔哪,道長(zhǎng)欢顷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任捉蚤,我火速辦了婚禮抬驴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缆巧。我一直安慰自己布持,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布陕悬。 她就那樣靜靜地躺著题暖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捉超。 梳的紋絲不亂的頭發(fā)上胧卤,一...
    開(kāi)封第一講書(shū)人閱讀 49,837評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音拼岳,去河邊找鬼灌侣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛裂问,可吹牛的內(nèi)容都是我干的侧啼。 我是一名探鬼主播牛柒,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼痊乾!你這毒婦竟也來(lái)了皮壁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哪审,失蹤者是張志新(化名)和其女友劉穎蛾魄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體湿滓,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滴须,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了叽奥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扔水。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖朝氓,靈堂內(nèi)的尸體忽然破棺而出魔市,到底是詐尸還是另有隱情,我是刑警寧澤赵哲,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布待德,位于F島的核電站,受9級(jí)特大地震影響枫夺,放射性物質(zhì)發(fā)生泄漏将宪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一橡庞、第九天 我趴在偏房一處隱蔽的房頂上張望较坛。 院中可真熱鬧,春花似錦毙死、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至除呵,卻和暖如春再菊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颜曾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工纠拔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泛豪。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓稠诲,卻偏偏與公主長(zhǎng)得像侦鹏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臀叙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚略水、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,736評(píng)論 0 14
  • 用兩張圖告訴你劝萤,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料渊涝? 從這篇文章中你...
    hw1212閱讀 12,699評(píng)論 2 59
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,131評(píng)論 30 470
  • 點(diǎn)贊再看,養(yǎng)成習(xí)慣床嫌,白嫖不好跨释,歡迎大家關(guān)注我面試小專(zhuān)欄 : iOS中高級(jí)進(jìn)階之路 有我準(zhǔn)備的一線大廠面試資料和簡(jiǎn)歷...
    iOS弗森科閱讀 4,301評(píng)論 1 35
  • 先談?wù)凧VM 這篇文章主要是講class文件和類(lèi)加載機(jī)制,但是整個(gè)過(guò)程都和jvm密切相關(guān)厌处,所以先從jvm說(shuō)起鳖谈。 J...
    Garwer閱讀 3,790評(píng)論 3 5