<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_沙加</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/17459/rss</id><updated>2011-10-10T06:44:46Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/17459/rss"/><entry><id>http://www.cnblogs.com/darkangle/archive/2011/10/10/2205564.html</id><title type="text">Google Closure 的单元测试纪要</title><summary type="text">setup 和 tearDown 在每个测试方法的开始和结束都会被执行。对于有 dom 结构改变的场景有时候是不可逆的改变，目前只能按一定顺序执行测试方法，使 setup 逻辑只执行一次。框架代码会自动检测以 &amp;quot;test&amp;quot; 开头的测试用例，执行顺序为字母顺序，如果希望按顺序执行测试则需要对命名作一些调整。fireClickSequence 会引发完整的按钮动作过程，比如 mouseDown, click, couseUp, 而 fireClickEvent 仅引发 click 事件，引发事件是直接采用生成对象然后执行 callback 的方法，并非原生的浏览器事件。goog</summary><published>2011-10-10T06:45:00Z</published><updated>2011-10-10T06:45:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/10/10/2205564.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/10/10/2205564.html"/><content type="html">&lt;ol&gt;&#xD;
&lt;li&gt;setup 和 tearDown 在每个测试方法的开始和结束都会被执行。对于有 dom 结构改变的场景有时候是不可逆的改变，目前只能按一定顺序执行测试方法，使 setup 逻辑只执行一次。&lt;/li&gt;&#xD;
&lt;li&gt;框架代码会自动检测以 "test" 开头的测试用例，执行顺序为字母顺序，如果希望按顺序执行测试则需要对命名作一些调整。&lt;/li&gt;&#xD;
&lt;li&gt;fireClickSequence 会引发完整的按钮动作过程，比如 mouseDown, click, couseUp, 而 fireClickEvent 仅引发 click 事件，引发事件是直接采用生成对象然后执行 callback 的方法，并非原生的浏览器事件。google 不推荐使用原生事件来进行测试。这些方法也不能用于生产环境。&lt;/li&gt;&#xD;
&lt;li&gt;对于依赖关系还未开发完整的可以使用 mock 对象定义覆盖掉原始对象定义。&lt;/li&gt;&#xD;
&lt;li&gt;异步请求目前使用 mock xhr 对象直接调用 callback 方法，并且提供静态方法获取刚刚发送的请求参数以验证程序工作的正确性。&lt;/li&gt;&#xD;
&lt;/ol&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2205564.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/10/10/2205564.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/09/27/2193243.html</id><title type="text">双飞翼布局的选区问题</title><summary type="text">http://blog.html.it/layoutgala/LayoutGala09.html象这样的布局在用鼠标选取左边内容的时候很容易造成选取的面积太大，经仔细分析是因为选区跨越了 display:float 元素的边界，暂时也没有特别好的解决方案，不过可以稍微优化一下，只要选取的开始区距文字不是太远就可以。将外围的定宽 div 两边多留一些白，比如 width:1000px (&amp;gt;a + b + c ), 然后左边的那一列给一个 margin 就行 ，比如 总宽是 960 那么 margin = (1000 - 960) / 2 ， 如果还觉得效果不够好，外面的还可以设宽些，现在最</summary><published>2011-09-27T08:01:00Z</published><updated>2011-09-27T08:01:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/09/27/2193243.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/09/27/2193243.html"/><content type="html">&lt;p&gt;http://blog.html.it/layoutgala/LayoutGala09.html&lt;/p&gt;&#xD;
&lt;p&gt;象这样的布局在用鼠标选取左边内容的时候很容易造成选取的面积太大，经仔细分析是因为选&lt;strong&gt;区跨越了 display:float 元素的边界&lt;/strong&gt;，暂时也没有特别好的解决方案，不过可以稍微优化一下，只要选取的开始区距文字不是太远就可以。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;将外围的定宽 div 两边多留一些白，比如 width:1000px (&amp;gt;a + b + c ), 然后左边的那一列给一个 margin 就行 ，比如 总宽是 960 那么 margin = (1000 - 960) / 2 ， 如果还觉得效果不够好，外面的还可以设宽些，现在最低的屏宽也应该在 1280 了吧。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2193243.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/09/27/2193243.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/09/26/2191167.html</id><title type="text">一个 JS 面试题目</title><summary type="text">看到一个 JS 题：只允许使用 +-*/ 和 Math.* ，求一个函数 y = f(x, a, b);当 x &amp;gt; 100 时返回 a 的值，否则返回 b 的值，不能使用 if else 等条件语句，也不能使用 |, ?, 数组试解如下:&amp;lt;script&amp;gt;function transition(x, a, b){	x = Math.max(x, 0); // 先处理负数。	if(x == 100){ return b;	}	var tmp = Math.ceil(Math.min(Math.max(x - 100, 0), 1));	return a*tmp + b*Math.</summary><published>2011-09-26T01:28:00Z</published><updated>2011-09-26T01:28:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/09/26/2191167.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/09/26/2191167.html"/><content type="html">&lt;p&gt;看到一个 JS 题：&lt;/p&gt;&#xD;
&lt;p&gt;只允许使用 +-*/ 和 Math.* ，求一个函数 y = f(x, a, b);&lt;/p&gt;&#xD;
&lt;p&gt;当 x &amp;gt; 100 时返回 a 的值，否则返回 b 的值，不能使用 if else 等条件语句，也不能使用 &amp;nbsp;|, ?, 数组&lt;/p&gt;&#xD;
&lt;p&gt;试解如下:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;script&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;function transition(x, a, b){&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt;x = Math.max(x, 0); // 先处理负数。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt;if(x == 100){&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt; &amp;nbsp; &amp;nbsp;return b;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt;var tmp = Math.ceil(Math.min(Math.max(x - 100, 0), 1));&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  style="white-space: pre;"&gt;	&lt;/span&gt;return a*tmp + b*Math.abs(tmp-1);&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(101, 1, 0));// 1&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(100.5, 1, 0));// 1&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(100, 1, 0)); //0&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(99.5, 1, 0));// 0&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(99, 1, 0));// 0&lt;/p&gt;&#xD;
&lt;p&gt;console.log(transition(-23, 1, 0));// 0&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一般思路是转换为 0, 1 的特殊值问题进行处理。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2191167.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/09/26/2191167.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/27/2155382.html</id><title type="text">HTML 5 之旅 part 1 - 无头苍蝇</title><summary type="text">一个相当无聊的东西，只是告诉你 html5 canvas 如何进行基本的使用：&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang=&amp;quot;zh-CN&amp;quot;&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;&amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge,chrome=1&amp;quot; /&amp;gt;&amp;lt;titl</summary><published>2011-08-27T03:16:00Z</published><updated>2011-08-27T03:16:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/27/2155382.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/27/2155382.html"/><content type="html">&#xD;
&lt;p&gt;一个相当无聊的东西，只是告诉你 html5 canvas 如何进行基本的使用：&lt;/p&gt;&#xD;
&lt;p align="center"&gt;&lt;textarea  rows="18" id="code1" style="width: 100%;"&gt;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang="zh-CN"&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&amp;gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /&amp;gt;&amp;lt;title&amp;gt;沙加 - HTML5 - Lesson 1&amp;lt;/title&amp;gt;&amp;lt;meta name="author" content="" /&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;div id="content"&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;script type="mce-text/javascript"&amp;gt;&#xD;
var MM = {};&#xD;
&#xD;
MM.bind = function(fn, selfObj, var_args) {&#xD;
  if (arguments.length &amp;gt; 2) {&#xD;
    var boundArgs = Array.prototype.slice.call(arguments, 2);&#xD;
    return function() {&#xD;
      var newArgs = Array.prototype.slice.call(arguments);&#xD;
      Array.prototype.unshift.apply(newArgs, boundArgs);&#xD;
      return fn.apply(selfObj, newArgs);&#xD;
    };&#xD;
&#xD;
  } else {&#xD;
    return function() {&#xD;
      return fn.apply(selfObj, arguments);&#xD;
    };&#xD;
  }&#xD;
};&#xD;
&#xD;
function $(id){&#xD;
    return document.getElementById(id);&#xD;
};&#xD;
&#xD;
MM.main = function(){&#xD;
    var m = $("content");&#xD;
    //m.innerHTML = "Hello world!";&#xD;
    &#xD;
    var canvas = document.createElement("CANVAS");&#xD;
&#xD;
    if(!canvas){&#xD;
        m.innerHTML = "Your browswer doesn't support Canvas element, please update.";&#xD;
        return;&#xD;
    }&#xD;
    &#xD;
    canvas.height = 200;&#xD;
    canvas.width = 200;&#xD;
    &#xD;
    m.appendChild(canvas);    &#xD;
    &#xD;
    //var game = new MM.PingBallGame(new MM.AbstractBrush(canvas));&#xD;
    var game = new MM.PingBallGame(new MM.CanvasBrush(canvas));&#xD;
    game.init();&#xD;
    &#xD;
    //MM.setUpDebugger();&#xD;
};&#xD;
&#xD;
MM.CanvasBrush = function(canvas){&#xD;
    this.ctx = canvas.getContext("2d");&#xD;
};&#xD;
&#xD;
MM.CanvasBrush.prototype.drawBall = function(xx, yy , opt_radius){&#xD;
    var x = parseInt(xx);&#xD;
    var y = parseInt(yy);&#xD;
    var r = opt_radius || 5;&#xD;
    this.ctx.beginPath();&#xD;
    this.ctx.moveTo(x, y);&#xD;
    this.ctx.arc(x, y, r, 0, Math.PI*2);&#xD;
    this.ctx.closePath();&#xD;
    this.ctx.fillStyle = "red";&#xD;
    this.ctx.fill();&#xD;
};&#xD;
MM.CanvasBrush.prototype.drawBackground = function(){&#xD;
    this.ctx.fillStyle = '#ddd';&#xD;
    this.ctx.fillRect(0, 0, 200, 200);&#xD;
};&#xD;
MM.CanvasBrush.prototype.clearAll = function(){&#xD;
    this.ctx.clearRect(0, 0, 200, 200);&#xD;
};&#xD;
&#xD;
MM.PingBallGame = function(brush){&#xD;
    this.brush = brush;&#xD;
    this.ballX = 20;&#xD;
    this.ballY = 20;&#xD;
    this.direction = 0;&#xD;
    this.speed = 30; //pixils per second.&#xD;
    this.refreshRate = 10; //15 picture per second.&#xD;
};&#xD;
&#xD;
MM.PingBallGame.prototype.init = function(){&#xD;
    //start roll the ball.&#xD;
    this.keepRoll();&#xD;
};&#xD;
&#xD;
MM.PingBallGame.prototype.keepRoll = function(){&#xD;
    this.direction += Math.PI*0.20*Math.random()*((+new Date())%2 == 0?1:-1);&#xD;
    var dx = this.speed/this.refreshRate*Math.cos(this.direction);&#xD;
    var dy = this.speed/this.refreshRate*Math.sin(this.direction);&#xD;
    &#xD;
    this.speed += 10;&#xD;
    &#xD;
    this.ballX += dx;&#xD;
    this.ballY += dy;&#xD;
    &#xD;
    if(this.ballY &amp;lt;= 5 || this.ballY &amp;gt;= 195 || this.ballX  &amp;lt;= 5 || this.ballX &amp;gt;= 195){&#xD;
        this.direction += Math.PI;&#xD;
        this.speed = 30;&#xD;
    }&#xD;
    &#xD;
    if(this.ballX &amp;lt;=5){&#xD;
       this.ballX = 5;&#xD;
    }&#xD;
    if(this.ballY &amp;lt;=5){&#xD;
       this.ballY = 5;&#xD;
    }&#xD;
    if(this.ballX &amp;gt;=195){&#xD;
       this.ballX = 195;&#xD;
    }&#xD;
    if(this.ballY &amp;gt;=195){&#xD;
       this.ballY = 195;&#xD;
    }&#xD;
    &#xD;
    this.brush.clearAll();&#xD;
    this.brush.drawBackground();&#xD;
    this.brush.drawBall(this.ballX, this.ballY);&#xD;
    &#xD;
    setTimeout(MM.bind(this.keepRoll, this), Math.floor(1000/this.refreshRate));&#xD;
};&#xD;
MM.main();&#xD;
&amp;lt;/script&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&#xD;
&#xD;
&lt;/textarea&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;input onclick="runEx('code1')" value="运行代码" onfocus="this.blur()" type="button" /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2155382.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/27/2155382.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/22/jquery-bind-delegate-live.html</id><title type="text">bind, delegate, live 三者的区别</title><summary type="text">简单总结如下：bind 直接绑定 handler 于元素上delegate 绑定事件在父级元素上live 绑定于 document 之上为啥有了 bind 还需要 delegate ?使用 deletegate 不需要为每一个元素都绑定事件处理器，并能处理动态创建的元素的 dom 事件。为啥 delegate 优于 live?它只作用于靠近目标目标元素的父级元素上，不需要冒泡到 document，在需要的时候可以停止冒泡事件；live 需要绑定于特定的 css 选择器，而 delegate 不需要，灵活性更高。为啥还要用 live?一般用于作用广泛的全站事件，比如 hovercard。</summary><published>2011-08-22T03:05:00Z</published><updated>2011-08-22T03:05:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/22/jquery-bind-delegate-live.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/22/jquery-bind-delegate-live.html"/><content type="html">&lt;p&gt;简单总结如下：&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;bind 直接绑定 handler 于元素上&lt;/li&gt;&#xD;
&lt;li&gt;delegate 绑定事件在父级元素上&lt;/li&gt;&#xD;
&lt;li&gt;live 绑定于 document 之上&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;div&gt;&lt;strong&gt;为啥有了 bind 还需要 delegate ?&lt;/strong&gt;&lt;/div&gt;&#xD;
&lt;div&gt;使用 deletegate 不需要为每一个元素都绑定事件处理器，并能处理动态创建的元素的 dom 事件。&lt;/div&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&#xD;
&lt;div&gt;&lt;strong&gt;为啥 delegate 优于 live?&lt;/strong&gt;&lt;/div&gt;&#xD;
&lt;div&gt;它只作用于靠近目标目标元素的父级元素上，不需要冒泡到 document，在需要的时候可以停止冒泡事件；live 需要绑定于特定的 css 选择器，而 delegate 不需要，灵活性更高。&lt;/div&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&#xD;
&lt;div&gt;&lt;strong&gt;为啥还要用 live?&lt;/strong&gt;&lt;/div&gt;&#xD;
&lt;div&gt;一般用于作用广泛的全站事件，比如 hovercard。&lt;/div&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2149026.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/22/jquery-bind-delegate-live.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/19/2145290.html</id><title type="text">Objective-C 学习笔记 - part 12 - 多线程</title><summary type="text">使用 @synchronized() 来标明一个同步的方法。实现同步的方式与其它语言类型，使用一个互斥锁，锁定对象决定了锁定范围的大小，比如锁定实例对象只对当前实例生效，锁定类对象对所有实例生效。当同步方法中的代码抛出异常时，运行时会解锁，让下面等待代码执行此同步方法...</summary><published>2011-08-19T01:32:00Z</published><updated>2011-08-19T01:32:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145290.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145290.html"/><content type="html">&lt;p&gt;使用 &lt;code&gt;@synchronized() 来标明一个同步的方法。&lt;/code&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;code&gt;实现同步的方式与其它语言类型，使用一个互斥锁，锁定对象决定了锁定范围的大小，比如锁定实例对象只对当前实例生效，锁定类对象对所有实例生效。&lt;/code&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;code&gt;当同步方法中的代码抛出异常时，运行时会解锁，让下面等待代码执行此同步方法...&lt;/code&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2145290.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145290.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/19/2145286.html</id><title type="text">Objective-C 学习笔记 - part 11 - 错误处理</title><summary type="text">Object-C 提供类似 Java / C＋＋风格的错误处理模型，当使用 -fobjc-exceptions 开关（gcc &amp;gt; 3.3）时，它可以工作，但是只限于 OS X v10.3 以后的版本，之前的版本并不提供这一支持。使用错误捕获的原则与其它语言类似：你不能用它来当作正常的处理流的判断条件，而把它仅仅当作“意外”可以使用多个 @catch 块来捕获不同的错误类型。Cup *cup = [[Cup alloc] init];@try { [cup fill];}@catch (NSException *exception) { NSLog(@&amp;quot;main: Caught </summary><published>2011-08-19T01:26:00Z</published><updated>2011-08-19T01:26:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145286.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145286.html"/><content type="html">&lt;p&gt;Object-C 提供类似 Java / C＋＋风格的错误处理模型，当使用 -fobjc-exceptions 开关（gcc &amp;gt; 3.3）时，它可以工作，但是只限于 OS X v10.3 以后的版本，之前的版本并不提供这一支持。&lt;br /&gt;&lt;br /&gt;使用错误捕获的原则与其它语言类似：你不能用它来当作正常的处理流的判断条件，而把它仅仅当作&amp;ldquo;意外&amp;rdquo;&lt;br /&gt;&lt;br /&gt;可以使用多个 @catch 块来捕获不同的错误类型。&lt;br /&gt;&lt;br /&gt;Cup *cup = [[Cup alloc] init];&lt;br /&gt;&amp;nbsp;&lt;br /&gt;@try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [cup fill];&lt;br /&gt;}&lt;br /&gt;@catch (NSException *exception) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NSLog(@"main: Caught %@: %@", [exception name], [exception reason]);&lt;br /&gt;}&lt;br /&gt;@finally {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [cup release];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;异常类可以是你自己实现的类，不过一般是 NSException 或者它的子类。&lt;br /&gt;&lt;br /&gt;更多关于错误处理的讨论见：&lt;br /&gt;http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html#//apple_ref/doc/uid/TP40001806&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2145286.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145286.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/19/2145266.html</id><title type="text">Objective-C 学习笔记 - part 10 - 选择器</title><summary type="text">在 object-c 中，selector 包含两种意义：在源文件中，它指向一个方法调用，在编译后它指向一个 unque indentifier。编译后的 selector 的类型为 SEL，同名的方法的选择器也相同。使用 selector 来调用object 方法是 Cocoa 框架 &amp;quot;目标－动作&amp;quot; 编程模型的基础。可以使用 @selector 来为 selector 创建一个别名：SEL setWidthHeight;setWidthHeight = @selector(setWidth:height:);在编译时用别名方法引用 seletor 不会对性能造成大的影响。</summary><published>2011-08-19T01:00:00Z</published><updated>2011-08-19T01:00:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145266.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145266.html"/><content type="html">&lt;p&gt;在 object-c 中，selector 包含两种意义：在源文件中，它指向一个方法调用，在编译后它指向一个 unque indentifier。&lt;br /&gt;&lt;br /&gt;编译后的 selector 的类型为 SEL，同名的方法的选择器也相同。&lt;br /&gt;&lt;br /&gt;使用 selector 来调用object &amp;nbsp;方法是 Cocoa 框架&amp;nbsp; "目标－动作" 编程模型的基础。&lt;br /&gt;&lt;br /&gt;可以使用 @selector 来为 selector 创建一个别名：&lt;br /&gt;&lt;br /&gt;SEL setWidthHeight;&lt;br /&gt;setWidthHeight = @selector(setWidth:height:);&lt;br /&gt;&lt;br /&gt;在编译时用别名方法引用 seletor 不会对性能造成大的影响。如果是运行时需要根据一个字会串动态决态调用哪个方法可以下面的形式，有点类似于反射：&lt;br /&gt;NSString *method;&lt;br /&gt;method = NSStringFromSelector(setWidthHeight);&lt;br /&gt;&lt;br /&gt;关于方法和选择器&lt;br /&gt;&lt;br /&gt;框架只为 selector 分配 identifier 鸸 不是方法的实现，因此不同 class 的同名方法虽然 selector 的 identifier 一样，但是在执行是与方法调用无异。同时静态方法也可以与动态方法重名，因为他们有不同的归属对象。&lt;br /&gt;&lt;br /&gt;动态类型标注时，同名方法必须是相同的参数类型与返回值，而静态类型标注时不需要。这是因为静态类型标注时可以通过类的元数据得知方法的实现。&lt;br /&gt;&lt;br /&gt;除此之外，静态方法和实例方法也不受此限制，他们存在于不同的空间。&lt;br /&gt;&lt;br /&gt;id&amp;nbsp;&amp;nbsp; helper = getTheReceiver();&lt;br /&gt;SEL&amp;nbsp; request = getTheSelector();&lt;br /&gt;[helper performSelector:request];&lt;br /&gt;&lt;br /&gt;如些的动态调用显得很强大。&lt;br /&gt;&lt;br /&gt;[myButtonCell setAction:@selector(reapTheWind:)];&lt;br /&gt;[myButtonCell setTarget:anObject];&lt;br /&gt;&lt;br /&gt;上面的代码演示了如何将按钮和事件处理对象进行关联&lt;br /&gt;&lt;br /&gt;虽然有一些手段使用动态 message 来维护按钮与事件处理对象的关系，但是苹果认为那会带来不必要的复杂性，因此使用了目前这种方式。&lt;br /&gt;&lt;br /&gt;为了避免对象接受到它不能处理的消息，多用静态标注类型总是好的，因为它可以在编译时被检查。&lt;br /&gt;&lt;br /&gt;如果一定要在运行时调用一个不能确定的方法，那么可以用这样的方式进行测试，以进行安全调用而不是报错：&lt;br /&gt;&lt;br /&gt;if ( [anObject respondsToSelector:@selector(setOrigin::)] )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [anObject setOrigin:0.0 :0.0];&lt;br /&gt;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fprintf(stderr, "%s can&amp;rsquo;t be placed\n",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [NSStringFromClass([anObject class]) UTF8String]);&lt;br /&gt;&lt;br /&gt;另外，当对象不能处理一个消息时，它可以对它进行转发。详见 消息转发： http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2145266.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/19/2145266.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/17/2143217.html</id><title type="text">Objective-C 学习笔记 - part 9 - 静态标记的类型</title><summary type="text">默认的动态行为：对象是动态类型推断的只有在运行时才分配内存消息是动态绑定的，对象只能执行它所理解的消息”方法调用“虽然动态执行让程序变得灵活，但是也少了编译时的类型检查，你可以使用静态类型来进行编译时检查。Rectangle *thisObject = [[Square alloc] init];象这样指定类型，基本上只影响到编译时的检查，其它的行为跟 typed as id 是一样的。好处；1。 静态类型检查2。显式的方法参数类型与返回值。3。允许你使用 structure pointer 直接访问对象的实例变量。使用静态类型后，如果一个对象没有响应一个它应该响应的消息，那么会报错把一个静态</summary><published>2011-08-17T07:49:00Z</published><updated>2011-08-17T07:49:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143217.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143217.html"/><content type="html">&lt;p&gt;默认的动态行为：&lt;br /&gt;对象是动态类型推断的&lt;br /&gt;只有在运行时才分配内存&lt;br /&gt;消息是动态绑定的，对象只能执行它所理解的消息&amp;rdquo;方法调用&amp;ldquo;&lt;br /&gt;&lt;br /&gt;虽然动态执行让程序变得灵活，但是也少了编译时的类型检查，你可以使用静态类型来进行编译时检查。&lt;br /&gt;&lt;br /&gt;Rectangle *thisObject = [[Square alloc] init];&lt;br /&gt;&lt;br /&gt;象这样指定类型，基本上只影响到编译时的检查，其它的行为跟 typed as id 是一样的。&lt;br /&gt;&lt;br /&gt;好处；&lt;br /&gt;1。 静态类型检查&lt;br /&gt;2。显式的方法参数类型与返回值。&lt;br /&gt;3。允许你使用 structure pointer 直接访问对象的实例变量。&lt;br /&gt;&lt;br /&gt;使用静态类型后，如果一个对象没有响应一个它应该响应的消息，那么会报错&lt;br /&gt;&lt;br /&gt;把一个静态类型的变量赋值给另一个静态类型 变量时，编译器保证它他们是相容的。&lt;br /&gt;&lt;br /&gt;重要：一般来说不同类的同名方法（selector ）需要使用同类型参数和返回值。这是因为运行值只为同名方法创建一份元数据。&lt;br /&gt;&lt;br /&gt;但是对于静态类型没有此限制。&lt;br /&gt;&lt;br /&gt;子类的实例可以标记为父类类型，以实现多态。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2143217.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143217.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/darkangle/archive/2011/08/17/2143187.html</id><title type="text">Objective-C 学习笔记 - part 8 - 快速枚举</title><summary type="text">快速枚举使用的语法：for ( TypenewVariable in expression ) { statements }orTypeexistingItem;for ( existingItem in expression ) { statements }枚举期间对象不能被改变。使用快速枚举的三个类：NSArray, NSDictionary, NSSet如何使用：NSArray *array = [NSArray arrayWithObjects: @&amp;quot;One&amp;quot;, @&amp;quot;Two&amp;quot;, @&amp;quot;Three&amp;quot;, @&amp;quot;Four&amp;qu</summary><published>2011-08-17T07:27:00Z</published><updated>2011-08-17T07:27:00Z</updated><author><name>沙加</name><uri>http://www.cnblogs.com/darkangle/</uri></author><link rel="alternate" href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143187.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143187.html"/><content type="html">&lt;p&gt;快速枚举使用的语法：&lt;br /&gt;for ( Type&amp;nbsp;newVariable in expression ) { statements }&lt;br /&gt;or&lt;br /&gt;Type&amp;nbsp;existingItem;&lt;br /&gt;for ( existingItem in expression ) { statements }&lt;br /&gt;&lt;br /&gt;枚举期间对象不能被改变。&lt;br /&gt;&lt;br /&gt;使用快速枚举的三个类：&lt;br /&gt;NSArray, NSDictionary, NSSet&lt;br /&gt;&lt;br /&gt;如何使用：&lt;br /&gt;&lt;br /&gt;NSArray *array = [NSArray arrayWithObjects:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @"One", @"Two", @"Three", @"Four", nil];&lt;br /&gt;&amp;nbsp;&lt;br /&gt;for (NSString *element in array) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NSLog(@"element: %@", element);&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @"quattuor", @"four", @"quinque", @"five", @"sex", @"six", nil];&lt;br /&gt;&amp;nbsp;&lt;br /&gt;NSString *key;&lt;br /&gt;for (key in dictionary) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NSLog(@"English: %@, Latin: %@", key, [dictionary objectForKey:key]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;也可以使用 enumeration :&lt;br /&gt;NSArray *array = [NSArray arrayWithObjects:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @"One", @"Two", @"Three", @"Four", nil];&lt;br /&gt;&amp;nbsp;&lt;br /&gt;NSEnumerator *enumerator = [array reverseObjectEnumerator];&lt;br /&gt;for (NSString *element in enumerator) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ([element isEqualToString:@"Three"]) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;NSString *next = [enumerator nextObject];&lt;br /&gt;// next = "Two"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/darkangle/aggbug/2143187.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/darkangle/archive/2011/08/17/2143187.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
