当前位置: 首页 > 编程日记 > 正文

Expandable Table的Demo

在网上看到一个可点击cell展开的TableView的demo,原文是swift语言,我写了个oc版,有兴趣的朋友可以看下:

效果:



oc源码(带中文注释):http://download.csdn.net/detail/dolacmeng/9419612

英文原文:http://www.appcoda.com/expandable-table-view

部分译文:

一般app是通过切换多个view controllers来与用户交互,这些view controllers可能只是简单地在屏幕上显示某类信息、让用户输入数据,有时我们可以使用expandable tableviews来实现需求,而不用创建新的view controllers。


和表面意思一样,expandable tableview是一种可以让它的cell展开或收起的tableview,当需要显示可选信息时,使用expandable tableviews是一个不错的选择,这样就不用创建多个view controllers来让用户输入数据了。例如,可以在不离开当前view controller的情况下,显示和藏起表格的某些选项。


在这篇博客,我将演示使用一个简单但高效的方法来创建expandable tableviews,当然这并不是实现这个效果的唯一的方法,更多的应该是根据你的app需求。但是我的目标是展示一个比较常规的、可以在大多数情况下重用的方法。所以,说了那么多,我们下一节就开始体验一下我们将要实现的功能。


关于这个Demo App

我们将要看下在一个包含tableview的view controller中,expandable tableview是怎么创建和工作的。我们先弄一个包含用户需要录入的数据的模拟表格,它包含下面三个section:

1 Personal  个人信息

2 Preferences  喜好

3 Work Experience 工作经验

每一个section将包含可展开的cell,它们可以显示和隐藏子cell。

每一个section的最顶层cell如下:


“Personal” section:

1   Full name:显示用户的全名

2   Date of birth:显示用户出生日期,当它展开时,会出现一个可选择日期的date picker view,和一个确定日期选择的按钮

3   Marital status:显示用户是否已经结婚,当它展开时,会出现一个switch控件来设置婚姻状况。


“Preferences” section:

1  喜欢的体育运动:我们的模拟表单会询问用户喜欢的体育运动,当用户点了这个cell,会展开四个选项,当用户从中选择后,会在此cell中显示选择的结果,并且四个选项被收起。

2  喜欢的颜色:和上面类似,只是这里是显示三个不同的颜色让用户选择。


“Work Experience” section:

Level: 当点击顶层cell展开后,会显示一个包含slider滑块的cell,让用户设设置工作经验等级,我们设定可选择的范围为0-10,并且为integer值。


下面的动态图会让你对我们要实现的效果有更清晰的了解:



你在前文中可能已经注意到了展开tableview后会有多种不同样式的cell,它们都是用xib来设计的,都是继承自UITableViewCell的子类—CustomerCell



在项目中,你会找到下面这些cell对应的xib文件:



它们的名字暗示了它们是哪种类型的cell,不过你可以先在项目工程中深入的探索一下。

除了cell,你会发现已经实现了的其它一些代码。虽然它们也很重要,但是这些代码不是这篇博客的核心,所以我已经写好并且会跳过它们。我们真正感兴趣的代码会在下面一步一步添加。

你已经了解了我们最终要实现的效果,所以我们就开始学习怎么去创建expandable tableview吧。

描述cell

我将要完成的expandable tableview的所有实现方法,都是基于一个简单思想:给app提供每个cell的描述信息。也就是让app知道哪些cell需要展开,哪些不需要、哪些需要显示,哪些不需要、label要显示什么字以及其它更多信息。实际上,全局思想是将包含cell的标记、cell中需要存储的值,以属性组的方式保存下来。然后,让app取得这些数据,正确地显示它们。

在这个demo app中,我创建和使用了下面表格中列出的属性。注意在实际app中,可以根据需求添加新的属性或者重命名它们。不管怎样,重要的是你得到下面这些数据,然后可以根据你期望的效果去修改。属性列表:

isExpandable:是个bool值,指示是否一个可以展开的cell,它是这篇博文中最重要的属性之一。

isExpanded: 是个bool值,指示一个可展开cell当前是展开还是收起状态。顶层的cell默认是收起,所以初始值都是NO

isVisible: 真如名字,表示是否可见。它在后面会扮演一个很重要的角色,基于这个属性来显示tableview中正确的cell.

value:这个属性是用来记录cell里面控件的值(例如,婚姻状况的switch开关的值)。并不是所有cell都含有控件,所以大部分这这个值会是空的。

primaryTitle: 主要标题的文字,有时是cell需要显示的实际值。

secondaryTitle: 副标题

cellIdentifier:对应custom cell的identifier,是用来获得对应cell的,同时也用来确定对应的动作事件以及确定cell的高度。

additionalRows: 包含子cell的总数量,就是展开时需要增加的总行数。


每一个单独的cell会用到上面这些属性,而我们会使用property list(plist)文件。在这个plist文件中,我们会给每个cell的属性都正确地赋值,而我们一行代码都不需要写。是不是很爽?

我们先在项目中创建一个新的plist文件,然后填充数据。但你没必要这样做,你可以直接下载已经准备好的.plist文件。下载并且添加到项目中即可,而不需要你再花费时间做意义不大的复制粘贴工作。

首先,你下载的文件名字为CellDescriptor.plist,最外层结构(root)是array数组,每一项代表tableview的一个section。也就是说最外层的array数组包含三项,数量等于我们希望在tableview中显示的数量(三项)。上面所说的这三项,分别也是一个array数组,每一项分别包含了每一个section中的cell的描述。实际上,每一个单独的cell的属性以字典的形式存储。这里是plist文件的例子:


现在,我们就花时间进一步看看我们准备在tableview中显示的cell的属性和对应的值。很容易理解,通过使用处理好的数据,我们需要编写来创建和管理可收起cell的代码显著地减少了,我们不再口述app中不同cell的状态(例如,哪些cell是展开的,是否可以展开cell,由代码决定某个cell是可见的还是不可见的,等等)。所有的信息都在你刚才下载的plist文件中。

加载Cell属性

是时候写一些代码了,虽然通过使用属性减少了很多代码量,还是需要往项目中添加一些代码。现在描述cell的plist文件已经存在了,首先我们必须通过代码来把内容加载为array数组。数组会在下一节中用作tableview的datasources。打开项目中的ViewController.swift 文件,在类的顶部声明下面的属性:

var cellDescriptors: NSMutableArray!

这个array数组将包含从plist加载的描述cell的字典。


下一步,实现一个新的自定义函数,来加载文件内容为array数组。我们把函数命名为loadCellDescriptors():

fun loadCellDescriptors() {if let path = NSBundle.mainBundle().pathForResource("CellDescriptor", ofType: "plist") {cellDescriptors = NSMutableArray(contentsOfFile: path)}
}

我们这里做的比较简单:确保plist文件在bundle的路径是有效的,然后通过加载文件内容初始化cellDescriptors数组

我们会在view显示(appear)之前和tableview配置好之后,才调用上面的函数。


override func viewWillAppear(animated: Bool) {super.viewWillAppear(animated)configureTableView()loadCellDescriptors()
}

如果你在上面代码片段最后一行调用打印命令,你会在控制台看到plist文件的内容。那代表了它们已经被成功地加载到内存中了。



一般地,我们这一节的内容应该完成了,但我们还会给下一节做必不可少的铺垫。或许你已经发现,并不是所有的cell都在app启动后是可见的,因为按不同的需求,它们可能是展开或者收起的。


从编程来说,行(row)的索引(index)不是固定的(我们写程序处理cell时的indexPath.row),因此,我们不能仅仅使用数据源的array数组的cell row来显示每一个cell。我们必须要有一个解决方案来提供可见行的索引(row index)。


所以,我们要实现一个新的函数,命名为getIndicesOfVisibleRows()。它的名字已经很清楚描述了它的目的:获得行索引(row index)对应的cell的值,而这里的cell指的是被标记为可见的cell。在我们实现之前,请再一次在类的头部声明:

var visibleRowsPerSection = [[Int]]()

这个二维数组会存储每一个section的可见的cell(第一维是section,第二维是row)。


现在我们来关注下这个新函数的实现。可能正如你所猜想,我们会遍历所有的cell描述,然后把所有“isVisible” 属性为YES的cell的索引(index)添加到上面的二维数组中。明显地,我们会处理一个嵌套循环,不过并不困难。这里是函数实现:

func getIndicesOfVisibleRows() {visibleRowsPerSection.removeAll()for currentSectionCells in cellDescriptors {var visibleRows = [Int]()for row in 0...((currentSectionCells as! [[String: AnyObject]]).count - 1) {if currentSectionCells[row]["isVisible"] as! Bool == true {visibleRows.append(row)}}visibleRowsPerSection.append(visibleRows)}
}

注意在开始的地方需要移除visibleRowsPerSection数组中所有之前的内容,否则我们会在随后的调用中出现错误的数据。另外,实现的代码是比较简单的,我就不进一步解释。


第一次调用上面函数是在文件被加载之后(后面还会再次调用)。所以重新看下我们这一节实现的第一个函数,我们改成下面这样:


func loadCellDescriptors() {if let path = NSBundle.mainBundle().pathForResource("CellDescriptor", ofType: "plist") {cellDescriptors = NSMutableArray(contentsOfFile: path)getIndicesOfVisibleRows()tblExpandable.reloadData()}
}

虽然tableview还不能工作,但我们触发了reload动作,所以我们可以确定在app启动后,是已经显示cell了。


显示Cells

每次启动app,都会加载cell的描述,我们现在开始处理并在tableview中显示cell。我们这节创建另外一个新的函数,来从cellDescriptors数组中返回正确的cell描述:

func getCellDescriptorForIndexPath(indexPath: NSIndexPath) -> [String: AnyObject] {let indexOfVisibleRow = visibleRowsPerSection[indexPath.section][indexPath.row]let cellDescriptor = cellDescriptors[indexPath.section][indexOfVisibleRow] as! [String: AnyObject]return cellDescriptor
}

上面函数接收的参数是tableview需要处理的cell的索引值,它会返回一个包含对应cell的所有属性的字典。首要任务是由传递来的索引找到可见行的实际索引,我们只需要cell的section和row。由于我们此时还未处理tableview的代理方法,所以你不需要知道代码的全貌,但我必须提前说明:每一个section的所有row的数目等于每一个section的可见cell的数目。也就是说上面实现中的任何indexPath.row的值与visibleRowsPerSection对应存储的cell的index相等。

通过每个cell的行索引(index of the row),我们可以从cellDescriptors数组中取出描述cell的字典。注意第二维数组的下标是indexOfVisibleRow,而不是indexPath.row。使用后者会返回错误数据。

让我们确定tableview方法。首先,确定tableview的section的数量:

func numberOfSectionsInTableView(tableView: UITableView) -> Int {if cellDescriptors != nil {return cellDescriptors.count}else {return 0}
}

你应该理解我们不应该忽略cellDescriptor数组为nil的情况。我们只在它被初始化并且设置了cell的描述数据时返回数组的数量。


然后,我们确定每个section包含的行数。正如我前面所说的,数量总是等于可见cell的数量,我们可以通过一行代码返回:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {return visibleRowsPerSection[section].count
}

然后,确定每个section的标题:

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {switch section {case 0:return "Personal"case 1:return "Preferences"default:return "Work Experience"}
}

然后,确定每一行的高度:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)switch currentCellDescriptor["cellIdentifier"] as! String {case "idCellNormal":return 60.0case "idCellDatePicker":return 270.0default:return 44.0}
}

有些东西我想在此强调一下:在这一部分的开始,我们第一次使用了getCellDescriptorForIndexPath函数,我们需要获得正确的cell描述,因为接下来需要取得“cellIdentifier”属性,需要根据它的值来确定行高。你可以在各自的xib文件中确定每一种类型cell的高的值。


最后,真正地显示cell:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)let cell = tableView.dequeueReusableCellWithIdentifier(currentCellDescriptor["cellIdentifier"] as! String, forIndexPath: indexPath) as! CustomCellreturn cell
}

我们再一次通过当前index的值获得正确的cell描述。通过“cellIdentifier” 属性来获得正确的cell样式:


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)let cell = tableView.dequeueReusableCellWithIdentifier(currentCellDescriptor["cellIdentifier"] as! String, forIndexPath: indexPath) as! CustomCellif currentCellDescriptor["cellIdentifier"] as! String == "idCellNormal" {if let primaryTitle = currentCellDescriptor["primaryTitle"] {cell.textLabel?.text = primaryTitle as? String}if let secondaryTitle = currentCellDescriptor["secondaryTitle"] {cell.detailTextLabel?.text = secondaryTitle as? String}}else if currentCellDescriptor["cellIdentifier"] as! String == "idCellTextfield" {cell.textField.placeholder = currentCellDescriptor["primaryTitle"] as? String}else if currentCellDescriptor["cellIdentifier"] as! String == "idCellSwitch" {cell.lblSwitchLabel.text = currentCellDescriptor["primaryTitle"] as? Stringlet value = currentCellDescriptor["value"] as? Stringcell.swMaritalStatus.on = (value == "true") ? true : false}else if currentCellDescriptor["cellIdentifier"] as! String == "idCellValuePicker" {cell.textLabel?.text = currentCellDescriptor["primaryTitle"] as? String}else if currentCellDescriptor["cellIdentifier"] as! String == "idCellSlider" {let value = currentCellDescriptor["value"] as! Stringcell.slExperienceLevel.value = (value as NSString).floatValue}return cell
}

对于一般的cell,我们只设置textLabel的主标题和detailTextLabel的副标题的文字值。在我们的demo app中,identifier 为idCellNormal的cell是顶层可以展开和收起的cell。


对于包含textfield的cell,我们只要通过“primaryTitle”属性来设置它的placeholder文字。


对于包含switch control的cell,我们需要做两件事:首先确定需要显示的文字(在我们的例子中这是固定的,可以在CellDescriptor.plist文件中修改),然后我们设置switch的正确状态,根据描述中是否是“on”来决定。注意后面我们可以改变这个值。


还有identifier为“idCellValuePicker” 的cell。这些cell会提供选项列表,当一个选项被选中时,父cell会自动收起。这些cell的文字在plist文件中确定。


最后,还有一种情况是包含一个slider。这里我们只是从currentCellDescriptor字典获得当前的值,我们把他转换为float数值,然后把它赋值给slider,使其始终显示正确的值(当其可见时)。如果我们改变它的值,需要更新cell描述中对应的值。


在这个demo中,对于identifiers没有在上面明确规定的,什么都不需要做。不过,如果你想用别的方法来处理它们,随意添加或修改代码。


现在,你可以运行这个app,看看现在的效果。不要期望太多,现在你只能看到顶层的cell。不要忘记我们还没有实现扩展的功能,所以你点击它们,并不会发生什么。不过,不要灰心,到目前为止我们完成的部分已经可以完美运行。


扩展和收起

我认为这一部分是你最期待的,因为这篇博文的实际目标会在这一节实现。首先我们要实现最顶层的cell被点击后扩展或者收起,然后对应的子cell根据需求出现或者隐藏。


首先我们需要知道被点击cell所在的行(记住,不是真正的indexPath.row,而是可见cell的行),所以我们在下面的tableview代理方法中通过一个变量来确定它:


func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
}

虽然不需要太多的代码来实现展开和收起,但我们还是一步步来,确保我能讲的彻底并且你能够明白。现在我们获得了被点击行真实的索引,我们必须检查cellDescriptors数组,判断我们对应的cell是否展开。在可展开,但是还没展开的情况下,我们会标记对应的cell需要展开,否则,我们会标记它为需要收起:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpandable"] as! Bool == true {var shouldExpandAndShowSubRows = falseif cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] as! Bool == false {// In this case the cell should expand.shouldExpandAndShowSubRows = true}}
}

一旦为上面的标记赋值,指示cell是否需要展开,我们就需要保存这个值到cell的描述中,换句话说,就是更新cellDescriptors数组。我们希望更新选中cell的“isExpanded”属性,它才能在以后的点击事件中正确地表现(在展开状态收起,在收起状态展开)。

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpandable"] as! Bool == true {var shouldExpandAndShowSubRows = falseif cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] as! Bool == false {shouldExpandAndShowSubRows = true}cellDescriptors[indexPath.section][indexOfTappedRow].setValue(shouldExpandAndShowSubRows, forKey: "isExpanded")}
}

还有一个重要的细节,我们要记得这一点:回想一下,在每个cell的描述中,都有一个名为“isVisible”的属性,说明一个cell是否应该显示。根据上面的标记,这个属性应该改变,所以当展开时,不可见的行变成可见的,当收起时,又变回隐藏的。实际上,通过改变这个属性我们实现了展开和收起的效果。所以,修改代码上面的片段,更新被点击的顶层cell的子cell

处理值

现在我们可以开始关注cell的输入数据以及用户交互了。首先,我们实现点击identifier为“idCellValuePicker”的cell的逻辑。在我们的demo的tableview中,“Preferences” section的cell以列表的形式列出了了喜爱的运动和颜色。虽然我已经提过它了,我认为复述一遍是个明智的选择,我们希望各自的顶层cell会收起并隐藏选项,同时选中的值在顶层cell中显示:


我选择从这种类型的cell开始讲起的实际原因是我们最后会继续用tableview的代理方法。我们会添加ELSE子句来处理不能展开的cell,然后,我们会检查被点击cell的identifier,如果identifier是“idCellValuePicker”,我们就得到了我们真正感兴趣的cell。


func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpandable"] as! Bool == true {...}else {if cellDescriptors[indexPath.section][indexOfTappedRow]["cellIdentifier"] as! String == "idCellValuePicker" {}}getIndicesOfVisibleRows()tblExpandable.reloadSections(NSIndexSet(index: indexPath.section), withRowAnimation: UITableViewRowAnimation.Fade)
}

在if子句内部,我们要完成明确的目的:

  1. 我们要找到被点击的cell的父cell的行索引。实际上,我们从点击行往前找,找到的第一个顶层cell就是我们要找的。
  2. 我们会把选中的cell的值显示到父cell中。
  3. 我们要标记父cell为非展开状态。
  4. 我们要标记找到的顶层cell所对应的所有子cell为不可见。

我们把这些都写成代码:


func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpandable"] as! Bool == true {...}else {if cellDescriptors[indexPath.section][indexOfTappedRow]["cellIdentifier"] as! String == "idCellValuePicker" {var indexOfParentCell: Int!for var i=indexOfTappedRow - 1; i>=0; --i {if cellDescriptors[indexPath.section][i]["isExpandable"] as! Bool == true {indexOfParentCell = ibreak}}cellDescriptors[indexPath.section][indexOfParentCell].setValue((tblExpandable.cellForRowAtIndexPath(indexPath) as! CustomCell).textLabel?.text, forKey: "primaryTitle")cellDescriptors[indexPath.section][indexOfParentCell].setValue(false, forKey: "isExpanded")for i in (indexOfParentCell + 1)...(indexOfParentCell + (cellDescriptors[indexPath.section][indexOfParentCell]["additionalRows"] as! Int)) {cellDescriptors[indexPath.section][i].setValue(false, forKey: "isVisible")}}}getIndicesOfVisibleRows()tblExpandable.reloadSections(NSIndexSet(index: indexPath.section), withRowAnimation: UITableViewRowAnimation.Fade)
}

我们再一次修改了某些cell的 “isVisible”属性,因此,可见cell的数量又改变了。很明显,最后两个函数调用是必须的。


现在,如果你允许app,你会看到app是怎么处理选择喜爱的运动和颜色的。


转载请注明出处:http://blog.csdn.net/dolacmeng/article/details/50591914


相关文章:

Java对多线程的支持

Java运行时系统实现了一个用于调度线程执行的线程调度器,用于确定某一时刻由哪一个线程在CPU上运行。在Java技术中,线程通常是抢占式的而不需要时间片分配进程(分配给每个线程相等的CPU时间的进程)。抢占式调度模型就是许多线程处…

ESP8266-iot-2

1.SDK概述 复制相关的工程文件到HelloWorld里面 要在版本esp8266_nonos_sdk_v2.0.0_16_07_19上面开发,那么就要复制相应文件 然后打开IDE 导入HelloWorld到工程里面 创建3个文件,如下图 再从lib里面添加文件 复制到我的下面 复制app里面的内容 打算从IoT…

iptables防火墙策略

环境: foundation1 172.25.1.250 172.25.254.1 server1 172.25.1.1 server2 172.25.1.2 server3 172.25.1.3 四个主机都做解析 iptables简介: netfilter/iptables(简称为iptables&#xf…

ubuntu(16.04.01)学习-day1

1.修改root用户密码 sudo passwd root 按提示进行设置。 2.从Ubuntu 16.04开始,用户可以实现改变启动器的位置,可以将启动器移到屏幕底部,但是无法移到右边或顶部。打开终端,然后输入下面这个命令,即可将启动器移到屏幕…

HDU 1090 A+B for Input-Output Practice (II)

#include <cstdio> int main() {int n,a,b;scanf("%d",&n);for (int i1; i<n; i){ scanf("%d%d",&a,&b);printf("%d\n",ab);}return 0; } 转载于:https://www.cnblogs.com/forever97/p/3539605.html

监听UIWebView点击视频播放的事件

最近项目需要统计在跳转UIWebView后&#xff0c;用户点击网页上的视频进行播放的概率。找了很多监听进入视频播放的方法&#xff0c;最后在stackoverflow找到下面这个使用Notification的可行方法(如果是弹出)&#xff1a; #pragma mark Notification - (void)addNotification {…

linux系统下redhat7之虚拟机控制

基础操作&#xff1a; [kioskfoundation0 Desktop]$ rht-vmctl start desktop ###开启desktop虚拟机 Error: desktop not started (is already running) ###报错&#xff0c;desktop已经运行 [kioskfoundation0 Desktop]$ rht-vmctl view desktop …

如何设计一个 iOS 控件?(iOS 控件完全解析)

前言 一个控件从外在特征来说&#xff0c;主要是封装这几点&#xff1a; 交互方式显示样式数据使用 对外在特征的封装&#xff0c;能让我们在多种环境下达到 PM 对产品的要求&#xff0c;并且提到代码复用率&#xff0c;使维护工作保持在一个相对较小的范围内&#xff1b;而一个…

Chapter12:动态内存

智能指针——shared_ptr为了更容易地使用动态内存&#xff0c;新的标准提供了智能指针来管理动态对象。智能指针的行为类似常规指针&#xff0c;重要的区别是它负责自动释放指向的对象。 智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。 1 if (p1 &am…

判断JS对象是否拥有某属性两种方式

方式&#xff0c;但稍有区别 1&#xff0c;in 运算符 1 2 3 var obj {name:jack}; alert(name in obj); // --> true alert(toString in obj); // --> true 可看到无论是name&#xff0c;还是原形链上的toString&#xff0c;都能检测到返回true。 2&#xff0c;hasOwnP…

Linux之redhat7系统结构

一.linux系统结构 linux是一个倒树结构 linux中所有的东西都是文件 这些文件都在系统顶级目录“/” /就是根目录 /目录以下为二级目录这些目录都是系统装机时系统自动建立的 二级目录的作用 /bin ##二进制可执行文件也就是系统命令 /sbin ##系统管理命令存放位置 /boot …

ASP.NET优化

源地址&#xff1a;http://www.cnblogs.com/wangjingblogs/archive/2013/02/27/2934706.html http://jingyan.baidu.com/article/2d5afd69bfd0ff85a3e28e6d.html转载于:https://www.cnblogs.com/haizine/p/5841771.html

3D Touch介绍: 一个数字压力器App和Quick Actions

随着iPhone 6s and 6s Plus的发布&#xff0c;苹果介绍了全新的手机交互方式&#xff1a;重按手势。你应该知道&#xff0c;这个特性其实早已应用在苹果手表和MacBook产品中&#xff0c;名字叫Force Touch。它给用户交互添加了全新的维度&#xff01; 或许你对Force Touch为什么…

一些LUA函数(转载)

转自http://hi.baidu.com/chevallet/item/9a3a6410c20d929198ce3363 一些LUA函数 1、assert (v [, message])  功能&#xff1a;相当于C的断言&#xff0c;当表达式v为nil或false将触发错误,  message&#xff1a;发生错误时返回的信息&#xff0c;默认为"assertion f…

cifs------网络文件系统(1)

SMB文件共享 SMB&#xff08;Server Message Block&#xff09;通信协议是微软&#xff08;Microsoft&#xff09;和英特尔(Intel)在1987年制定的协议&#xff0c;主要是作为Microsoft网络的通讯协议。SMB 是在会话层&#xff08;session layer&#xff09;和表示层&#xff0…

Swift 教學:如何使用iOS Charts API 製作漂亮的圖表

在應付許多的資料時&#xff0c;比起只在表格中呈現&#xff0c;使用圖表來顯示資料&#xff0c;可以幫助使用者容易地了解資訊。有了圖表&#xff0c;相對於讀取整個資料表&#xff08;或幾個資料表&#xff09;你可以輕鬆地一眼便見到以圖形表示的資料&#xff0c;取得所需的…

在Proteus中添加标号

1.Proteus中添加组件后双击引脚可以快速生成一个最近的端口。 2.按A调出设置界面 3.在String中写&#xff1a;netH#,"H"可以换成自定义前缀。count为起始值&#xff0c;increment为增量。 4.依次点击想要编号的引脚。转载于:https://www.cnblogs.com/viaduct/p/58424…

九度OJ 1525 子串逆序打印 -- 2012年Google校园招聘笔试题目

题目地址&#xff1a;http://ac.jobdu.com/problem.php?pid1525 题目描述&#xff1a; 小明手中有很多字符串卡片&#xff0c;每个字符串中都包含有多个连续的空格&#xff0c;而且这些卡片在印刷的过程中将字符串的每个子串都打印反了&#xff0c;现在麻烦你帮小明将这些字符…

cifs------网络文件系统(2)

接着上篇博客继续&#xff1a; Samba 基本配置 [rootserver2 ~]# rpm -qc samba-common //查看smb的配置文件 1、黑、白名单的设定 默认白名单&#xff0c;设置的ip是黑名单用户&#xff1a;hosts deny ip 默认黑名单&#xff0c;设置的ip是白名单用户&#xff…

iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

原文地址&#xff1a;https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/02_Parse的网络缓存与离线存储/iOS网络缓存扫盲篇.md 目录 当我们在谈论缓存的时候&#xff0c;我们在谈论什么&#xff1f;GET网络请求缓存 80%的缓存需求&#xff1a;两行代码就可满足…

YARN集群维护部分问题汇总

云梯开发人员在云梯Yarn集群的搭建和维护过程中做了许多工作&#xff0c;本文选择这期间部分较为典型的问题&#xff0c;通过对这些问题的分析和解决方案&#xff0c;为大家分享分布式系统问题调查的经验。 调查的问题 1. 2013年初引入社区0.23时&#xff0c;调查ResourceManag…

linux系统管理及vim

1.管理输入输出 在linux系统中&#xff0c;正确输出的编号为1&#xff0c;错误输出编号为2 在系统中用普通用户执行 "student" find /etc -name passwd 因为student用户权限问题会有以下输出 find: ‘/etc/pki/CA/private’: Permission denied ##没有进入权力…

如何用 OS X 的 Xcode 写C语言程序

這篇是給新手看的。 如果你在 Windows 習慣使用 Visual C 或 Dev-C 的話&#xff0c;到了 Mac OS X 可能會突然不知道要怎麼寫程式&#xff0c;尤其當你已經用 Visual C 的 Debugger 用得很上手的話。 最近我們系上的課充滿了 C programming&#xff0c;我也稍微摸懂了 Xcode 的…

【转】初等数论 ——原根、指标及其应用

转自&#xff1a;http://blog.163.com/gc_chdch126/blog/static/172279052201641935828402/ 学习总结&#xff1a;初等数论&#xff08;3&#xff09;——原根、指标及其应用 2016-05-19 15:58:28| 分类&#xff1a; 信息学——学习总 | 标签&#xff1a;初等数论 数学 |…

互联网产品评论索引

这里收集一些评论文章&#xff0c;定期查看文章观点的正确性&#xff0c;索引持续更新中 网站前期如何获得推广资源 专访陶瑾&#xff1a;微信公众平台开发先行者转载于:https://www.cnblogs.com/needrunning/p/3000353.html

Apache服务器部署(1)

apache&#xff08;web服务器&#xff09;简介&#xff1a; Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;其跨平台和安全性被广泛使用&#xff0c;是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充&…

JavaScript关键字this指向

在js中this始终指向一个调用函数的那个对象 var a有种你干掉我啊; //纯粹调用函数 function test(){ console.log(this.a);//默认指向全局对象 } //test();//>windows.test() //作为对象的方法被调用 Function.prototype.logfunction(){ console.log(this.a); } //此时t为一…

项目开发过程中的收获与思考

2013年7月&#xff0c;我正式毕业了&#xff0c;到公司入职&#xff0c;也就正式成为了一名菜鸟程序员。到今天&#xff0c;2014年1月3日&#xff0c;目前主要的工作是公司一个项目中的一个功能模块&#xff0c;到我进入项目组算起&#xff0c;已经过了四个月了。因此&#xff…

【仿汽车之家】价格区间选择控件

仿照汽车之家iOS客户端“找车”栏目的价格区间选择控件&#xff0c;最终实现效果如下&#xff1a; 一、界面实现 *根据屏幕大小以及刻度的大小&#xff0c;宏定义需要用到的一些值 #define SCREENW [UIScreen mainScreen].bounds.size.width #define SCREENH [UIScreen mainScr…

Apache服务器部署(2)

签名CA证书 环境&#xff1a;server1:172.25.1.1 重置虚拟机 挂载yum源 [rootserver1 ~]# yum install mod_ssl -y //下载ssl模块 [rootserver1 ~]# yum install crypto-utils -y //安装加密软件 [rootserver1 ~]# genkey …