您的位置:首页 > 移动开发 > Swift

Swift教程_通过改造官方Sample学习Swift(五)_swift重写Sample(构建数据层)

2014-10-22 11:10 483 查看
Swift教程_通过改造官方Sample学习Swift(一)_Element示例简介

Swift教程_通过改造官方Sample学习Swift(二)_Swift基础(简单值、控制流、方法和闭包)

Swift教程_通过改造官方Sample学习Swift(三)_Swift基础(对象和类、枚举和结构、协议和扩展、泛型)

Swift教程_通过改造官方Sample学习Swift(四)_swift重写Sample(搭建程序结构、构建storyboard)

Swift教程_通过改造官方Sample学习Swift(五)_swift重写Sample(构建数据层)

Swift教程_通过改造官方Sample学习Swift(六)_swift重写Sample(构建控制层)

Swift教程_通过改造官方Sample学习Swift(七)_swift重写Sample(构建展示层)

Swift教程_通过改造官方Sample学习Swift(八)_swift重写Sample(添加View的动画效果、添加View的阴影)

Swift教程_通过改造官方Sample学习Swift(九)_总结

3.构建数据层

按照官方sample,我们使用简单的plist来保存数据(当然使用内置数据库也ok)。该plist既是我们列表中需要显示的内容。

1.将化学元素的数据整理为Elements.plist,该plist的结构为Array<Dictionary>(java表示为ArrayList<Map<String,Object>>)。

dictionary中包含若干键值对,但一定要保证每个dictionary键值对的键和值的类型一致,这样我们才能够进行数据的解析。如图。



2. 在ElementDataModel目录下创建PKOElementDataModel类,作为化学元素的实体类,其中声明plist中所包含的键值对(由于部分属性没有使用,我这里就偷个懒省略了)。

由于我们的需求是要根据化学元素的状态种类来显示不同的底色,所以我们这里声明两个图片类型的属性,一个作为列表中行的左侧图标,另一个作为明细页面的展示用背景图,并重写他们的get方法,根据化学元素的状态种类来返回所需要的图片。

由于我们从plist仅能获得dictionary,所以我们需要进行转换,将从plist读出的dictionary转换为PKOElementDataModel对象,于是我们要写一个转换方法initWithDictionary(aDictionary : NSDictionary) ->PKOElementDataModel。

代码如下。

import UIKit//swift部分包不需要import,但是ui还是要import进来才会生效

class PKOElementDataModel {
    
    var atomicNumber:Int = 0//前面说过,swift必须要对属性进行初始化,当然也可以用?来定义可选属性
    var name:String = ""//所有属性均使用swift类型,当然也可以使用NSString、NSNumber
    var symbol:String = ""
    var state:String = ""
    var atomicWeight:String = ""
    var discoveryYear:String = ""
    var group:Int = 0
    var period:Int = 0
    
    var imageForDetailElementTileView:UIImage{
        get{
            return UIImage(named:self.state+"_256")
        }
    }
    
    var imageForCellIconElementView:UIImage{
        get{
            return UIImage(named:self.state+"_37")
        }
    }
    
    func initWithDictionary(aDictionary : NSDictionary) ->PKOElementDataModel{//个人并不认为这种方法是合理的,但是sample就是这么干的,照抄了
        self.atomicNumber = aDictionary["atomicNumber"] as Int
        self.atomicWeight = aDictionary["atomicWeight"] as String
        self.discoveryYear = aDictionary["discoveryYear"] as String
        self.name = aDictionary["name"] as String
        self.symbol = aDictionary["symbol"] as String
        self.state = aDictionary["state"] as String
        self.group = aDictionary["group"] as Int
        self.period = aDictionary["period"] as Int
        return self
    }
}

3.构建好了实体类后,我们需要一个能够从plist读取数据的服务类PKOElementDataService,该类声明了我们展示列表需要的多种array及dictionary实体,并在类初始化时解析plist并组装对应的array及dictionary。

首先,我们需要一个单例的服务,所以需要创建一个单例对象sharedElementDataService,这里用了gcd技术,保证单例。

其次,由于需求要不同维度的数据,所以我们需要按照不同维度进行分类和排序。

代码如下。

import UIKit

class PKOElementDataService {//这里的“元素”均指业务上的化学元素,不要误会为技术词汇
    var elementDictionarys = [String:PKOElementDataModel]()//[元素名字:元素对象]
    
    var symbolLetterArray = [String]()
    var stateArray = [String]()
    
    var elementByNameArray = [PKOElementDataModel]()
    var elementByNumberArray = [PKOElementDataModel]()
    var elementSymbolDictionarys = [String:[PKOElementDataModel]]()//[元素简称首字母:元素对象集合]
    var elementStateDictionarys = [String:[PKOElementDataModel]]()//[元素状态:元素对象集合]
    
    struct Inner {//单例模式的对象
        static var instance: PKOElementDataService?
        static var token: dispatch_once_t = 0
    }
    
    class var sharedElementDataService: PKOElementDataService {//使用gcd技术保证线程安全
    dispatch_once(&Inner.token) {
        Inner.instance = PKOElementDataService()
        }
        return Inner.instance!
    }
    
    init() {
        self.initElementArray()
    }
    
    func initElementArray() {
        var thePath = NSBundle.mainBundle().pathForResource("Elements", ofType: "plist")!
        
        var elementArray = NSArray(contentsOfFile: thePath)//解析plist
        
        self.elementDictionarys = [String:PKOElementDataModel]()
        self.elementStateDictionarys = [String:[PKOElementDataModel]]()
        self.elementSymbolDictionarys = [String:[PKOElementDataModel]]()
        
        self.stateArray = [String]()
        self.symbolLetterArray = [String]()
        
        for elementArrayDictionary in elementArray {
            
            var elementDataModel = PKOElementDataModel().initWithDictionary(elementArrayDictionary as NSDictionary)
            self.elementDictionarys[elementDataModel.name] = elementDataModel
            if (self.elementStateDictionarys[elementDataModel.state] != nil) {
                self.elementStateDictionarys[elementDataModel.state]?.append(elementDataModel)
            } else {
                self.stateArray.append(elementDataModel.state)
                self.elementStateDictionarys[elementDataModel.state] = [PKOElementDataModel]()
                self.elementStateDictionarys[elementDataModel.state]?.append(elementDataModel)
            }
            
            var symbolLetter = elementDataModel.symbol.substringToIndex(advance(elementDataModel.symbol.startIndex, 1))//获取首字母,需要用advance构建一个String.index,具体方法请看advance的官方文档
            
            if (self.elementSymbolDictionarys[symbolLetter] != nil) {
                self.elementSymbolDictionarys[symbolLetter]?.append(elementDataModel)
            } else {
                self.symbolLetterArray.append(symbolLetter)
                
                self.elementSymbolDictionarys[symbolLetter] = [PKOElementDataModel]()
                self.elementSymbolDictionarys[symbolLetter]?.append(elementDataModel)
            }
        }
        
        self.elementByNameArray = self.presortElementsByName()
        
        self.elementByNumberArray = self.presortElementsByNumber()
        
        self.symbolLetterArray = self.presortSymbolLetters()
        for letter in self.symbolLetterArray {
            self.presortElementsBySymbol(letter as String)
        }
        
        self.stateArray = self.presortStates()
        for state in self.stateArray {
            self.presortElementsByState(state as NSString)
        }
    }
    
    // sort the elementsSortedByName array
    func presortElementsByName() -> [PKOElementDataModel] {//下面多个方法分类别为元素集合排序
        var values = self.elementDictionarys.values
        var sortedElements = values.array.sorted({
            (s1, s2) -> Bool in
            return s2.name > s1.name
        })
        return sortedElements
    }
    
    // sort the elementsSortedByNumber array
    func presortElementsByNumber() -> [PKOElementDataModel] {
        var values = self.elementDictionarys.values
        var sortedElements = values.array.sorted({
            (s1 , s2) -> Bool in
            return s1.atomicNumber > s2.atomicNumber
        })
        return sortedElements
    }
    
    // sort the symbolLetter array
    func presortSymbolLetters() -> [String] {
        var keys = self.elementSymbolDictionarys.keys
        var sortedElement = keys.array.sorted({
            (s1 , s2) ->Bool in
            return s2 > s1
        })
        return sortedElement
    }
    
    // sort the elementsSortedByName array
    func presortElementsBySymbol(letter : String) {
        self.elementSymbolDictionarys[letter]?.sort({
            (s1 , s2) ->Bool in
            return s1.name > s2.name
        })
    }
    
    // sort the state array
    func presortStates () -> [String]{
        var keys = self.elementStateDictionarys.keys
        var sortedElements = keys.array.sorted({
            (s1 , s2) ->Bool in
            return s2 > s1
        })
        return sortedElements
    }
    
    // sort the elementsSortedByName array
    func presortElementsByState (state : String) {
        
        self.elementStateDictionarys[state]?.sort({
            (s1 , s2) ->Bool in
            return s2.name > s1.name
        })
    }
}


4.由于我们需要将组装好的数据应用于tableView,而tableView提供一种方便的做法,就是实现UITableViewDatasource类,并重写其中方法。
我们先来构建一个定义这4类数据集的协议PKOTableDataSourceProtocol: UITableViewDataSource,当然,其中应包含一个方法,即通过索引获取数据对象。
代码如下。

import UIKit

protocol PKOTableDataSourceProtocol: UITableViewDataSource{
    
    var name: String{ get }//tabBarItem名称
    var navigationBarName: String{ get }//导航标题
    var tabBarImage: UIImage{ get }//tabBarItem图标
    var tableViewStyle: UITableViewStyle{ get }//table样式
    
    func elementDataModelForIndexPath(indexPath: NSIndexPath) ->PKOElementDataModel//通过索引获取数据对象
}


5.构造4个类,实现PKOTableDataSourceProtocol协议,实现UITableViewDataSource需要实现的tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell、tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int两个方法;以及PKOTableDataSourceProtocol需要实现的elementDataModelForIndexPath(indexPath: NSIndexPath)
->PKOElementDataModel方法;当然根据不同需求可以实现UITableViewDataSource中其他的方法。
代码如下。我只粘了2段具有代表性的,其他请下载源码

import UIKit

class PKOTableByNameDataSource: NSObject, PKOTableDataSourceProtocol {
    
    var name : String{
        get{
            return "Test1"
        }
    }
    
    var navigationBarName : String{
        get{
            return "test1"
        }
    }
    
    var tabBarImage : UIImage{
        get{
            return UIImage(named: "name_tab")
        }
    }
    
    var tableViewStyle : UITableViewStyle{
        get{
            return UITableViewStyle.Plain//平铺格式,对应的Grouped可以去查一下什么效果。
        }
    }
    
    func elementDataModelForIndexPath(indexPath: NSIndexPath) -> PKOElementDataModel {
        return PKOElementDataService.sharedElementDataService.elementByNameArray[indexPath.row]
    }
    
    //Asks the data source for a cell to insert in a particular location of the table view.(required)
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCellWithIdentifier("ElementTableViewCell", forIndexPath: indexPath) as PKOElementTableViewCell//根据标识获取我们自定义的TableViewCell
        var element = self.elementDataModelForIndexPath(indexPath)//根据索引获取对象
        cell.element = element
        return cell
    }
    
    //Tells the data source to return the number of rows in a given section of a table view. (required)
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return PKOElementDataService.sharedElementDataService.elementByNameArray.count//返回数据中对应分组的总数
    }

}
import UIKit

class PKOTableByStateDataSource: NSObject, PKOTableDataSourceProtocol {
    
    var name : String{
        get{
            return "Test4"
        }
    }
    
    var navigationBarName : String{
        get{
            return "test4"
        }
    }
    
    var tabBarImage : UIImage{
        get{
            return UIImage(named: "state_tab")
        }
    }
    
    var tableViewStyle : UITableViewStyle{
        get{
            return UITableViewStyle.Plain
        }
    }
    
    func elementDataModelForIndexPath(indexPath: NSIndexPath) -> PKOElementDataModel {
        var state = PKOElementDataService.sharedElementDataService.stateArray[indexPath.section]
        return PKOElementDataService.sharedElementDataService.elementStateDictionarys[state]![indexPath.row]
    }
    
    //Asks the data source for the title of the header of the specified section of the table view.
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
        return PKOElementDataService.sharedElementDataService.stateArray[section]//根据组索引获取对应组名称
    }
    
    //Asks the data source to return the titles for the sections for a table view.
    func sectionIndexTitlesForTableView(tableView: UITableView) -> [String] {
        return PKOElementDataService.sharedElementDataService.stateArray//获取组名称集合
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCellWithIdentifier("ElementTableViewCell", forIndexPath: indexPath) as PKOElementTableViewCell
        var element = self.elementDataModelForIndexPath(indexPath)
        cell.element = element
        return cell
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var state = PKOElementDataService.sharedElementDataService.stateArray[section]
        return PKOElementDataService.sharedElementDataService.elementStateDictionarys[state]!.count
    }
    
    //Asks the data source to return the number of sections in the table view.
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return PKOElementDataService.sharedElementDataService.stateArray.count
    }

}

点击进入ooppookid的博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐