主要学习与运行效果

在本节的内容中,我们将通过一个具体实例的实现过程,详细讲解在表视图当中,如何创建一个可展开可收缩的表视图。为了让读者有着更为直观的印象,我们将通过模仿QQ好友列表来实现这个效果。

该示例主要演示:

1.表视图外观设计

2.自定义用户组设计

3.从plist文件中读取数据

4.将数据显示在表视图中

5.实现表格的展开、收缩效果

运行效果如下所示:

表视图外观设计

我们使用Single View Application模板创建一个swift项目,命名为Friend List,为了简便起见,Devices我们选择iPhone进行开发。

打开Main.storyboard文件,删除View Controller Scene,从Xcode右下方的Object Library面板中将Navagation Controller拖动到故事板中,如下图所示:

Navigation Controller Scene包含了两个视图,一个是导航视图,一个是表视图。选中Navagation Controller Scene,取消Use Size Classes选项,勾选Is Initial View Controller选项,将其作为初始视图控制器运行。

设置完成后,故事板将如下图所示:

选 中Root View Controller的导航栏,修改其标题为“联系人”。完成此操作后,选择Table View中的Table View Cell,在Identifier项中输入:FriendCellIdentifier来为其增加标识符。对于Xcode来说,每一种表视图单元格都需要 声明其标识符,以让Xcode能够对其进行定位。如图所示:

此时的单元格高度还比较窄,为了能够达到我们想要的结果,我们需要设置其高度,同时也因为其高度固定,因此我们定位到单元格的Size inspector中,将Row Height设置为66(或者其他你看起来舒服的值)。如图所示:

向单元格中添加一个Image控件,两个Label控件,以完成粗略的QQ好友信息设计。设计效果如下图所示:

由于我们创建了一个自定义的表视图单元格,因此我们最好为其创建一个专门的类来定义其结构,以便以后能够借用此数据结构来保存从文件中读取的信息。

创建一个Friend.swift文件,文件内容如下:

import UIKit
class Friend: NSObject {
    var Avatars: String =  "user_default"   // 图片名称,定义朋友的头像
    var Name: String = ""           // 字符串,定义朋友的名字
    var Intro: String = ""            // 字符串,定义朋友的个性签名
    var VIP: Bool = false     // 布尔值,确定朋友是否为VIP
}

其中,user_default文件为用户默认头像,已经放置在Image.xcassets中,用户可以自行添加你喜爱的头像并放置在xcassets中。

然后我们创建一个FriendCell.swift文件,这个文件将和我们刚刚创建的那个单元格进行绑定。文件内容如下:

import UIKit
class FriendCell: UITableViewCell {
    @IBOutlet weak var ImgAvatars: UIImageView!
    @IBOutlet weak var LblName: UILabel!
    @IBOutlet weak var LblIntro: UILabel!
    var friend: Friend = Friend()
    // 设置朋友信息
    func setFriend(newfriend: Friend) {
        var Image: UIImage? = UIImage(named: "\(newfriend.Avatars)")
        if Image != nil {
            ImgAvatars.image = Image!
        }else{
            ImgAvatars.image = UIImage(named: "user_default")
        }
        LblName.text = newfriend.Name
        LblIntro.text = newfriend.Intro
        if friend.VIP {
            LblName.textColor = UIColor.redColor()
        }else{
            LblName.textColor = UIColor.blackColor()
        }
    }
}

其中,ImgAvatars与单元格中的Image控件进行绑定,LblName和LblIntro分别与单元格中的两个Label控件进行绑定。注意此时单元格的Identify inspector中的Class要设置为我们刚刚创建的FriendCell类。

接下来的代码就比较直观。这里我们对头像的读取进行了一个可选值的判定。首先先根据记录中的头像名称去读取存储好的头像。如果没有读取成功,那么Image变量将会返回一个nil值,这时就将头像设置为我们默认的头像:user_default。

自定义用户组设计

在iOS应用中,我们可以自定义表视图单元格的风格,其实原理就是向单元格中添加子视图。添加子视图的方法主要有三种:使用代码、从.xib文件加载以及直接使用storyboard进行设计。在上一节中我们就是使用storyboard进行设计,非常方便和直观。

在本节自定义用户组中,我们要设计单元格折叠后的父类单元格。出于代码的简便和直观起见,同时为了也为了让读者尽可能多的掌握自定义表视图的方法,因此这里我们采用.xib文件进行加载。

新建一个xib文件,依次选择New File -> iOS -> User Interface -> Empty,命名为SectionHeaderView

。这样我们就创建了一个xib文件。由图中可以看到,xib文件和storyboard的区别并不是很大。简单理解来说,可以把StoryBoard看做是一组viewController对应的xib,以及它们之间的转换方式的集合。

我 们强烈建议大家采用storyboard进行界面设计,因为storyboard是iOS 5之后苹果提供的以及强烈建议开发者使用的配置。但是,由于storyboard中已经不允许有单个view的存在,因此在某些时候我们还是需要借助于单 个的xib来自定义UI。这是由于storyboard的设计理念造成的。storyboard重视层次结构,重视UI的架构和设计,更重视项目的流程。 而对于单个的UI来说,则更注重于重用和定制。

向xib界面中拖入一个View,将其Attributes inspector中的Size修改为Freeform(允许调整View的大小),Status Bar修改为None(取消状态栏显示)。

向view中拖入一个Button控件和Label控件,适当调整大小,如图所示:

这时我们同样需要创建一个类来定义这个自定义用户组的数据结构,新建一个Group.swift文件,文件内容如下:

import UIKit
class Group: NSObject {
    var name: String = ""       // 字符串,定义组名称
    var friends: NSArray = NSArray()    // 数组,定义了该组内所有朋友
}

接下来,我们需要为我们自定义的表视图创建一个类来与之进行绑定。创建一个SectionHeaderView.swift文件,文件内容如下:

import UIKit
// 该协议将被用户组的委托实现; 当用户组被打开/关闭时,它将通知发送给委托,来告知Xcode调用何方法
protocol SectionHeaderViewDelegate: NSObjectProtocol {
    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int)
    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionClosed: Int)
}
class SectionHeaderView: UITableViewHeaderFooterView {
    @IBOutlet weak var LblTitle: UILabel!
    @IBOutlet weak var BtnDisclosure: UIButton!
    var delegate: SectionHeaderViewDelegate!
    var section: Int!
    var HeaderOpen: Bool = false  // 标记HeaderView是否展开
    override func awakeFromNib() {
        // 设置disclosure 按钮的图片(被打开)
        self.BtnDisclosure.setImage(UIImage(named: "carat-open"), forState: UIControlState.Selected)
        // 单击手势识别
        var tapGesture = UITapGestureRecognizer(target: self, action: "btnTap:")
        self.addGestureRecognizer(tapGesture)
    }
    @IBAction func btnTap(sender: UITapGestureRecognizer) {
        self.toggleOpen(true)
    }
    func toggleOpen(userAction: Bool) {
        BtnDisclosure.selected = !BtnDisclosure.selected
        // 如果userAction传入的值为真,将给委托传递相应的消息
        if userAction {
            if HeaderOpen {
                delegate.sectionHeaderView(self, sectionClosed: section)
            }
            else {
                delegate.sectionHeaderView(self, sectionOpened: section)
            }
        }
    }
}

使用协议的原因是SectionHeaderView是我们自定义的一个视图,而且我们专门为其新建了一个类文件来进行管理。……这 个协议定义了两个方法,这两个方法名称相同,但是参数不同,被称为函数重载。在接下来我们的使用中,可以直接使用Selector选择其参数名来进行调 用。

awakeFromNib()是.nib文件被加载的时候,创建view对象前调用的方法。其和viewDidLoad()的区别是, 当view对象被加载到内存时系统才会调用viewDidLoad()方法。因此,Xcode会先执行awakeFromNib()方法,才会执行 viewDidLoad()方法。

那为什么我们要用awakeFromNib()方法呢,那是因为UITableViewHeaderFooterView里面并不存在viewDidLoad()方法,我们没有办法对其重载调用,所以只能使用awakeFromNib()方法。

由于向.xib文件中直接添加手势,会导致该nib文件注册失败,因此我们用代码的形式来定义一个单击手势。这个手势将控制单元格的展开和收缩。

最 后要注意的是,由于我们的类继承的是UITableViewHeaderFooterView,虽然在UIKit中,这个类是UIView的子类,但是由 于swift还不完善的原因,在IB面板中(包括xib文件和storyboard文件)的Identity inspector的Class项中都不能够显示出我们刚刚创建出来的类,但是我们可以手动输入这个类的名称。

此时我们仅仅只是定义了SectionHeaderView.xib的属性和方法,但是由于用户组里面会包含多个FriendCell,因此我们还要在定义一个类来标明Group和SectionHeaderView之间的结构联系。

新建一个SectionInfo.swift文件,文件内容如下:

import Foundation
// 定义了用户组以及FriendCell的一系列属性、方法
class SectionInfo: NSObject {
    var group: Group = Group()
    var headerView: SectionHeaderView = SectionHeaderView()
}

至此,所有的表格结构、数据结构已经定义完成,接下来就是要从数据层面进行操作了。

从plist文件中读取数据

为了方便数据管理,我们使用数据持久化功能来保存用户组信息和朋友信息。这里我们采用属性列表来保存数据。应用程序在启动时会将该文件的全部内容读入内存,并在退出时注销。

新 建一个plist文件,依次选择New File -> iOS -> Resource -> Property List,命名为FriendInfo。这样我们就创建了一个plist文件。将文件中的Property List Type修改为None,然后按照下图所示设计文件内容:

接下来打开ViewController.swift文件,创建一个函数,命名为loadFriendInfo,用来读取文件。函数如下:

func loadFriendInfo() -> NSArray {
    var FriendInfo: NSMutableArray?
    // 定位到plist文件并将文件拷贝到数组中存放
    var fileUrl = NSBundle.mainBundle().URLForResource("FriendInfo", withExtension: "plist")
    var GroupDictionariesArray = NSArray(contentsOfURL: fileUrl!)
    FriendInfo = NSMutableArray(capacity: GroupDictionariesArray!.count)
    // 遍历数组,根据组和单元格的结构分别赋值
    for GroupDictionary in GroupDictionariesArray! {
        var group: Group = Group()
        group.name = GroupDictionary["GroupName"] as String
        var friendDictionaries: NSArray = GroupDictionary["Friends"] as NSArray
        var friends = NSMutableArray(capacity: friendDictionaries.count)
        for friendDictionary in friendDictionaries {
            var friendAsDic: NSDictionary = friendDictionary as NSDictionary
            var friend: Friend = Friend()
            friend.setValuesForKeysWithDictionary(friendAsDic)
            friends.addObject(friend)
        }
        group.friends = friends
        FriendInfo!.addObject(group)
    }
    return FriendInfo!
}

我们来逐次分析这个函数。首先我们需要定位到我们创建的FriendInfo.plist文 件,NSBundle.mainBundle中保存了一系列当前项目的信息,包括版本号、程序名等等内容,这里我们使用URLForResource() 来获取FriendInfo.plist的URL地址。

NSArray的contentsOfURL:

由此,我们就完成了从plist文件中读取数据的操作,接下来我们可以使用FriendInfo数组里面的值,来完成值的赋予。

将数据显示在表视图中

有了上面的操作,现在我们就可以将我们读取到的数据显示在表视图当中了。

我们首先定义一个类型为NSArray数组的变量,用来存放我们读取后的数据,以及存放用户组、单元格信息的NSMutableArray变量:

var groups: NSArray!
var sectionInfoArray: NSMutableArray!

接下来,我们在viewDidLoad()方法中添加如下语句,完成数据的读取和存放:

self.tableView.sectionHeaderHeight = CGFloat(HeaderHeight)    // 用户组高度
opensectionindex = NSNotFound
groups = loadFriendInfo()
let sectionHeaderNib: UINib = UINib(nibName: "SectionHeaderView", bundle: nil)
self.tableView.registerNib(sectionHeaderNib, forHeaderFooterViewReuseIdentifier: SectionHeaderViewIdentifier)

后面两个语句本章后面会对其详细介绍。

接下来,我们从父类视图中重写viewWillAppear方法,来完成分组表的定义。

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    // 检查SectionInfoArray是否已被创建,如果已被创建,则检查组的数量是否匹配当前实际组的数量。通常情况下,您需要保持SectionInfo与组、单元格信息保持同步。如果扩展功能以让用户能够在表视图中编辑信息,那么需要在编辑操作中适当更新SectionInfo
    if sectionInfoArray == nil || sectionInfoArray.count != self.numberOfSectionsInTableView(self.tableView) {
        // 对于每个用户组来说,需要为每个单元格设立一个一致的SectionInfo对象
        var infoArray: NSMutableArray = NSMutableArray()
        for group in groups {
            var dictionary: NSArray = (group as Group).friends
            var sectionInfo = SectionInfo()
            sectionInfo.group = group as Group
            sectionInfo.headerView.HeaderOpen = false
            infoArray.addObject(sectionInfo)
        }
        sectionInfoArray = infoArray
    }
}

接下来依次实现这几个方法:

override func canBecomeFirstResponder() -> Bool {
    return true
}

判断一个对象是否可以成为第一响应者。默认返回false。

如果一个响应对象通过这个方法返回true,那么它成为了第一响应对象,并且可以接收触摸事件和动作消息。

我们的UITableView是UIView的子类,因此必须重写这个方法才可以成为第一响应者。

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.groups.count
}

numberOfSectionsInTableView()方法返回表视图有多少个section。一个用户组对应一个section。

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    var sectionInfo: SectionInfo = sectionInfoArray[section] as SectionInfo
    var numStoriesInSection = sectionInfo.group.friends.count
    var sectionOpen = sectionInfo.headerView.HeaderOpen
    return sectionOpen ? numStoriesInSection : 0
}

tableView:numberOfRowsInSection:方法返回对应的section中有多少个元素,也就是多少行。在这里我们先确定用户组是否被打开,如果打开则返回对应的用户组中的所有朋友数量,否则为0。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let FriendCellIdentifier = "FriendCellIdentifier"
    var cell: FriendCell = tableView.dequeueReusableCellWithIdentifier(FriendCellIdentifier) as FriendCell
    var group: Group = (sectionInfoArray[indexPath.section] as SectionInfo).group
    cell.friend = group.friends[indexPath.row] as Friend
    cell.setFriend(cell.friend)
    return cell
}

tableView:cellForRowAtIndexPath:方法返回指定的行的单元格。一个朋友对应一个单元格。在这个方法 中,我们通过dequeueReusableCellWithIdentifier()方法来读取对应标识符的单元格,在这里是我们在 main.Stroyboard中定义的那个单元格。还记得我们给那个单元格添加了“FriendCellIdentifier”标识符吗?

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    // 返回指定的section header视图
    var sectionHeaderView: SectionHeaderView = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier(SectionHeaderViewIdentifier) as SectionHeaderView
    var sectionInfo: SectionInfo = sectionInfoArray[section] as SectionInfo
    sectionInfo.headerView = sectionHeaderView
    sectionHeaderView.LblTitle.text = sectionInfo.group.name
    sectionHeaderView.section = section
    sectionHeaderView.delegate = self
    return sectionHeaderView
}

和上面的方法相似,tableView:viewForHeaderInSection:方法返回section中的表头 (Header)类型。我们的SectionHeaderView声明的是UITableViewHeaderFooterView类型,这个方法是专门 用来返回该类型的实例的。

可以看到,这个方法中使用了和上面方法极其相似的 dequeueReusableHeaderFooterViewWithIdentifier()方法。这个方法的作用同样也是读取对应标识符的单元 格。不过不同的是,使用这个方法前需要注册nib文件或者注册描述这个单元格的类。因此,之前我们就使用了如下两条语句注册nib文件,以便于swift 能够读取到这个单元格。

let sectionHeaderNib: UINib = UINib(nibName: "SectionHeaderView", bundle: nil)
self.tableView.registerNib(sectionHeaderNib, forHeaderFooterViewReuseIdentifier: SectionHeaderViewIdentifier)
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return CGFloat(DefaultRowHeight)
}

这个方法返回指定的单元格的高度,这里我们返回的是单元格的默认高度。

实现表格的展开、收缩效果

我们给ViewController这个类继承SectionHeaderViewDelegate协议,此时,类的头部变成这样:

class ViewController: UITableViewController, SectionHeaderViewDelegate

接下来,我们在ViewController类中实现协议中定义的两个函数:

func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int) {
    var sectionInfo: SectionInfo = sectionInfoArray[sectionOpened] as SectionInfo
    sectionInfo.headerView.HeaderOpen = true
    //创建一个包含单元格索引路径的数组来实现插入单元格的操作:这些路径对应当前节的每个单元格
    var countOfRowsToInsert = sectionInfo.group.friends.count
    var indexPathsToInsert = NSMutableArray()
    for (var i = 0; i < countOfRowsToInsert; i++) {
        indexPathsToInsert.addObject(NSIndexPath(forRow: i, inSection: sectionOpened))
    }
    // 创建一个包含单元格索引路径的数组来实现删除单元格的操作:这些路径对应之前打开的节的单元格
    var indexPathsToDelete = NSMutableArray()
    var previousOpenSectionIndex = opensectionindex
    if previousOpenSectionIndex != NSNotFound {
        var previousOpenSection: SectionInfo = sectionInfoArray[previousOpenSectionIndex] as SectionInfo
        previousOpenSection.headerView.HeaderOpen = false
        previousOpenSection.headerView.toggleOpen(false)
        var countOfRowsToDelete = previousOpenSection.group.friends.count
        for (var i = 0; i < countOfRowsToDelete; i++) {
            indexPathsToDelete.addObject(NSIndexPath(forRow: i, inSection: previousOpenSectionIndex))
        }
    }
    // 设计动画,以便让表格的打开和关闭拥有一个流畅的效果
    var insertAnimation: UITableViewRowAnimation
    var deleteAnimation: UITableViewRowAnimation
    if previousOpenSectionIndex == NSNotFound || sectionOpened < previousOpenSectionIndex {
        insertAnimation = UITableViewRowAnimation.Top
        deleteAnimation = UITableViewRowAnimation.Bottom
    }else{
        insertAnimation = UITableViewRowAnimation.Bottom
        deleteAnimation = UITableViewRowAnimation.Top
    }
    // 应用单元格的更新
    self.tableView.beginUpdates()
    self.tableView.deleteRowsAtIndexPaths(indexPathsToDelete, withRowAnimation: deleteAnimation)
    self.tableView.insertRowsAtIndexPaths(indexPathsToInsert, withRowAnimation: insertAnimation)
    opensectionindex = sectionOpened
    self.tableView.endUpdates()
    }

我们来解析一下这个函数。首先创建了一个包含单元格索引路径的数组来实现插入单元格的操作,这个数组存放有将要打开的用户组 中的所有朋友信息。接下来是创建了一个包含单元格索引路径的数组来实现删除单元格的操作。首先将先前已打开的用户组关闭(调用toggleOpen()函 数),随后将数组中放入已打开的用户组中的所有朋友信息。

最后,执行删除行的操作,再执行插入行的操作,注意顺序不要颠倒了(想想为什么?)

我们使用beginUpdates()方法和endUpdates()方法将删除、插入操作“包”了起来,这两个方法是配合起来使用的,标记了一个tableView的动画块,分别代表动画的开始和结束。

func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionClosed: Int) {
    // 在表格关闭的时候,创建一个包含单元格索引路径的数组,接下来从表格中删除这些行
    var sectionInfo: SectionInfo = self.sectionInfoArray[sectionClosed] as SectionInfo
    sectionInfo.headerView.HeaderOpen = false
    var countOfRowsToDelete = self.tableView.numberOfRowsInSection(sectionClosed)
    if countOfRowsToDelete > 0 {
        var indexPathsToDelete = NSMutableArray()
        for (var i = 0; i < countOfRowsToDelete; i++) {
            indexPathsToDelete.addObject(NSIndexPath(forRow: i, inSection: sectionClosed))
        }
        self.tableView.deleteRowsAtIndexPaths(indexPathsToDelete, withRowAnimation: UITableViewRowAnimation.Top)
    }
    opensectionindex = NSNotFound
}

和上面的方法类似,在此我们不做过多的解释了。

到这里,我们的教程就结束了。有兴趣的同学可以去我的 Github 上面下载demo项目的源代码:TVAnimationsGestures-Swift,这个 demo 是苹果官方提供的 demo 的 Swift 版本,大家可以基于这个版本来实现可展开可收缩的表视图。

Swift 可展开可收缩的表视图的更多相关文章

  1. iOS开发高级分享 - iOS的可折叠表视图

    导言 我曾经开发过一个iphone应用程序,它显示了大量的输入,这些输入分为不同的类别,在`UITableView`...若要更改其中一个输入的值,用户按下表视图中的对应行,并在出现的单独屏幕中更改该 ...

  2. 表视图控制器(TableViewController)(三) 、 表视图搜索

    1 乐库的设置界面 1.1 问题 tableView分为静态(static)和动态(dynamic),之前使用的都是动态的tableView,表视图的有多少分区.有多少行以及每一行显示的内容都不是固定 ...

  3. 表视图控制器(TableViewController)(二)

    1 tableView的编辑模式 1.1 问题 表视图可以进入编辑模式,当进入编辑模式就可以进行删除.插入.移动单元等操作,本案例还是使用联系人界面学习如何进入编辑模式,以及进入编辑模式之后的删除.插 ...

  4. 表视图(UITableView)与表视图控制器(UITableViewController)

    表视图(UITableView)与表视图控制器(UITableViewController)其实是一回事. 表视图控制器是一种只能显示表视图的标准视图控制器,可在表视图占据整个视图时使用这种控制器.虽 ...

  5. iOS开发之多表视图滑动切换示例(仿"头条"客户端)---优化篇

    前几天发布了一篇iOS开发之多表视图滑动切换示例(仿"头条"客户端)的博客,之所以写这篇博客,是因为一位iOS初学者提了一个问题,简单的写了个demo做了个示范,让其在基础上做扩展 ...

  6. iOS开发之表视图爱上CoreData

    在接触到CoreData时,感觉就是苹果封装的一个ORM.CoreData负责在Model的实体和sqllite建立关联,数据模型的实体类就相当于Java中的JavaBean, 而CoreData的功 ...

  7. iOS企业级开发初级课程-表视图(13集)

    首先了解了表视图的组成.表视图类的构成.表视图的分类以及表视图的两个重要协议(委托协议和数据源协议),对表视图有了一个整体上的认识.接下来我们掌握了如何实现简单表视图和分节表视图,以及表视图中索引.搜 ...

  8. mysql常用表/视图管理语句

    查看所有表  show tables; 查看表/视图结构 desc 表名/视图名: 查看建表过程  show create table 表名: 查看建视图过程 show create view 视图名 ...

  9. 表视图控制器(TableViewController)(一)

    1 创建一个UITableViewController并展示简单数据 1.1 问题 有很多移动客户端的应用都是采用表的形式来展示数据,因为表视图能使数据看起来更规整.更有调理,比如微信界面就是使用的表 ...

随机推荐

  1. c++,operator=

    operator=为什么值得注意? 从语法上讲,下面的程序可以编译通过,我在另一篇笔记示例里面也这样用了. class A1 { public: int operator=(int a)//参数是in ...

  2. C-最长回文子串(2)

    在上一篇的文章中说到了,最长回文子串的问题,并且提到了基本的解决办法,即暴力求解法.效率O(N^3) 中心法求最长回文子串 我们知道回文字符串是以字符串中心对称的,如abba以及aba等.一个更好的办 ...

  3. HDOJ 1325 并查集

    跟小希的迷宫基本一样,只是此题是有向图,要注意:1无环 2 只有一个入度为0的结点(根结点), 不存在入度大于1的结点.输入结束条件是两个负数,而不是-1,不然会TLE. #include<st ...

  4. H5前端面试题及答案(2)

    最近想着跳槽,但面试的邀约不多,内心有点烦躁.梳理梳理心情,跳槽季竞争也大,努力做好自己... 21.请设计一套方案,用于确保页面中js加载完全. <!doctype html> < ...

  5. PHP - 判断php是否对表单数据内的特殊字符自动转义

    get_magic_quotes_gpc 有两个返回值: 0:在php.ini文件中已经关闭自动转移. 1:在php.ini文件中已经开启自动转移. 由此函数进行判断表单是否转移: /** * * m ...

  6. ean128与code128 条形码 算法分析

    [code128条形码组成] 除终止符(STOP)由13个模块组成外,其他字符均由11个模块组成 就是说,如果用‘1’表示黑线(实模块),用‘0’表示白线(空模块),那么每表示一个字符就需要11条线, ...

  7. 基于visual Studio2013解决C语言竞赛题之1038数字验证

          题目 解决代码及点评 /********************************************************************** ...

  8. wxWidgets帮助文档(1)

    IMPLEMENT_APP IMPLEMENT_APP(className) 这是在应用程序中使用类的实现文件的应用程序类wxWidgets动态建筑.你用这个代替Old form: MyApp myA ...

  9. How to decompile class file in Java and Eclipse - Javap command example(转)

    Ability to decompile a Java class file is quite helpful for any Java developer who wants to look int ...

  10. java学习笔记-继承中super关键字

    背景: 在java继承的概念中我们得知,被声明为私有的类成员对所属的类来说仍然是私有的.类之外的任何代码都不能访问,包括子类. super关键字的两种用法: 1.用于调用超类的构造函数: 2.用于访问 ...