git在错误分支上提交后的修正

应该在A分支上做的改动,不小心在B上改动并提交了,过了好几天才发现,此时需要做的操作包括,把这个提交移到A分支上,同时在B分支上把这个提交删除

移到A分支上很简单,在A分支上执行

1
git cherry-pick commitId

即可,有冲突的话,解决冲突

在B分支上的删除也简单,直接在B分支上执行

1
git reset commitId

这里的commitId是需要删除的提交之前的那个提交,然后把不想要的提交去掉,重新commit即可。这里写个简单的示例流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
touch a.txt
git add a.txt
git commit -m "add a"

touch b.txt
git add b.txt
git commit -m "add b"

git reset d9a3249 #这是add a之前的那个提交
git status #此时可以看到a.txt和b.txt都是Untracked files,也就是从add a之后的所有提交都变成了没有add的状态

rm -rf a.txt
git add b.txt
git commit -m "reset" #完成,add a这个提交已经没有了,而且在sourceTree上也看不到这次提交了

git reset d9a3249这步,也可以添加–soft参数,这个参数可以让所有的改动是已经add的状态,可以省掉之后再add一次,但要移除修改,则需要执行git rm –cached

tableview的一个优化方案

方案说明

使用scrollView + bakeLayer(android) + batchNode(ios)来代替tableview。适用于tableCell数量不是很多且结构简单,但占用了大尺寸图片的情况。例如

example

这里中间的滑动界面,第一反应就使用了tableview来做。后来想在性能上做优化的时候,使用了scrollView + bakeLayer来代替。实现上很简单,只要将一个layer作为scrollview的container,并让其bake即可,构造时设定好每个cell的坐标。

官方关于bake的介绍点击这里

为什么要用scrollview

为什么tableView不能直接使用bake呢? 注意事项里对于子节点经常会变的层, 启用bake功能,会给游戏性能带来额外的开销,建议对于不常修改子节点的层才开启该功能

tableview的实现,会不停地将tableCell添加和移除,所以肯定不能直接取tableView的container出来直接bake

细节

这里的实现需要稍微注意的两点有:

  1. container的尺寸要大于等于scrollView的尺寸,否则滑动时容易显示异常。如果container尺寸大于scrollView时,注意是否需要设置初始位移。
  2. 添加触摸事件时,把触摸点坐标转换成container内的坐标,再根据各个cell在container内的位置即可判断点击了哪个cell

代码

直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
var cellheight = 206; //单元格高度
var cellcount = 6; //单元格数量
var row = Math.ceil(cellcount * 0.5);
var containerHeight = Math.max(cellheight * row, h);
var scrollHeight = h; //scrollview高度
var scrollsize = cc.size(w, scrollHeight);

var container = new cc.Layer();
container.setContentSize(cc.size(w, containerHeight));

var scrollView = this._scrollview = cc.ScrollView.create(scrollsize, container);
scrollView.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL);
scrollView.setPosition(cc.p(0, 119));
this.addChild(scrollView);

//因为方向是从上往下,如果container高度超出,则需要设置初始位移
var delta = scrollHeight - containerHeight;
if (delta < 0) {
scrollView.setContentOffset(cc.p(0, delta), false)
}


for (var i = 0; i < cellcount; i++) {
var s1 = new cc.Sprite("#hall_enter_" + i + ".png");
var posx = i % 2 == 0 ? w * 0.25 : w * 0.75;
var posy = containerHeight - (Math.floor(i / 2) + 0.5) * cellheight;
s1.setPosition(posx, posy);
container.addChild(s1);
}
container.bake();


var bTouchCanceled = false;
var touchBeganPos = cc.p(0, 0);
var that = this;
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: false,
onTouchBegan: function(touch, event) {
var bounding = scrollView.getBoundingBox();
var pos = touch.getLocation();
if (cc.rectContainsPoint(bounding, pos)) {
bTouchCanceled = false;
touchBeganPos = pos;
return true;
}
return false;
},
onTouchEnded: function(touch, event) {
if (bTouchCanceled) {
return;
}
var loc = container.convertToNodeSpace(touch.getLocation());
var col = loc.x < w * 0.5 ? 0 : 1;
var row = Math.floor((containerHeight - loc.y) / cellheight);
var index = 2 * row + col;
that.onCellNodeClick(index);
},
onTouchCancelled: function() {
bTouchCanceled = true;
},

onTouchMoved: function(touch, event) {
var loc = touch.getLocation();
if (Math.abs(loc.x - touchBeganPos.x) > 10 || Math.abs(loc.y - touchBeganPos.y) > 10) {
bTouchCanceled = true;
}
}
}, container);

batchNode也是同理,我们抛弃tableCell,直接把组件添加到scrollView的container内,就可以使用batch功能了。

tableViewCell上的触摸事件

1.tableCellTouched

这是最简单的处理tableViewCell上触摸事件的方法了,接口为

1
tableCellTouched:function (table, cell){}

它是基于对整个tableView的触摸,所以优先级会低于tableViewCell上的事件。

2.对tableViewCell添加事件

这个就是比较坑的了,我们知道tableView在滚动中,会把屏幕外的tableViewCell从container中移除

1
this.getContainer().removeChild(cell, true);

这里cleanup参数为true,也就意味着对这个cell绑定的所有事件都会被移除,所以如果直接对tableViewCell进行绑定事件,当这个cell被重用时,它的绑定事件已经无影无踪,不会再有响应了。如果只是触摸事件,那么直接用tableCellTouched接口即可,如果确实需要绑定特殊事件例如CustomEventListener,那需要将listener存起来,在tableCellAtIndex接口中每次都进行绑定,当然也可以重写tableCellView的onEnter方法,在里面添加。

3.tableCellView内子控件添加事件

例如往tableCellView内添加controlButton,这时候即使cell被重用,触摸事件仍然会响应,因为cleanup并不会递归对子节点调用,所以事件会被保留。(这里理解错误,cleanup会对所有子孙结点递归调用,移除其触摸事件。之所以controlbutton事件被保留了,是因为它在onEnter方法里重新添加了)不过在添加触摸事件时要小心,例如这段代码

1
2
3
4
5
6
7
8
9
10
11
12
tableCellAtIndex: function(table, index) {
var cell = table.dequeueCell();
if (!cell) {
var cell = new cc.TableViewCell();
var button = new cc.ControlButton(new cc.LabelTTF("test", "Arial", 16), back)
cell.addChild(button);
button.addTargetWithActionForControlEvents(this, function(sender, event) {
console.log(index);
}, cc.CONTROL_EVENT_TOUCH_UP_INSIDE)
}
return cell;
}

这里点击按钮后显示的index肯定与期望的不一致,原因就是addTargetWithActionForControlEvents时传递的闭包内使用的index是tableViewCell构造时的index,当这个Cell被重用时,当前的index和构造时候的index很可能就不一致了。尤其是如果tableView方向是TABLEVIEW_FILL_TOPDOWN的话,tableView在构造时就发生了一次cell重用。如果希望显示正确的结果,必须使用cell当前的index来获取数据,也就是

1
2
3
4
button.addTargetWithActionForControlEvents(this, function(sender, e){
var idx = cell.getIdx();
console.log(idx);
}, cc.CONTROL_EVENT_TOUCH_UP_INSIDE)

不使用controlButton,而是自己给子控件添加事件处理,也是一样的方法。