加载中…
博文
标签:

switch

语句

break

case

冒号

default

分类: Objective-C选择结构
switch 语句,某种意义上说是 if-else 语句的延伸,常用于一个变量的值与不同的值连续进行比较。它的一般格式如下:

switch (expression_r)
{
    case value1:
        program statement
        program statement
          ...
        break;

    case value2:
        program statement
        program statement
          ...
        break;

      ...

    case valuen:
        program statement
        program statement
          ...
        break;

    default:
        program statement
        program statement
          ...
        break;
}

括在圆括号中的 expression_r 与 value1,value2,...  valuen 连续进行比较,后者必须是单个常量或常量表达式。如果发现某种情况下某个 value 值与 expression_r 的值相等,就执行该情况之后的程序语句。注意,包含多条的程序语句时,它们不必括在圆括号中。

break 语句表示一种特定情况的结束,并导致 switch 语句的终止。记住,每种情况的结尾都包含 break 语句。如果忘记为特点的情况执行这项操作,只要执行这种情况,程序就会继续执行下一种情况。有时需要有意这样做,如果选择这样的方式,请务必插入注释以便将你的目的告知他人。

如果 expression_r 的值不与任何情况的值匹配,将执行一种特殊的,名为 default 的可选情况。这在概念上等价于在 if else 中使用 else。接下来我们尝试把前文《直接识别运算符来进行计算的 Calculator 类》中的范例 6-8 用 switch 语句来进行代码上的替换,成为新的范例 6-9:

001 // Program to evaluate simple expression_rs of the form number operator number
002 
003 #import <Foundation/Foundation.h>
004 
005 @interface CalculatorNSObject
006 {
007     double accumulator;
008 }
009 
010 // accumulator methods
011 -(void)        setAccumulator: (double) value;
012 -(void)        clear;
013 -(double)    accumulator;
014 
015 // arithmetic methods
016 -(void)        add: (double) value;
017 -(void)        subtract: (double) value;
018 -(void)        multiply: (double) value;
019 -(void)        divide: (double) value;
020 
021 @end
022 
023 
024 @implementation Calculator
025 
026 -(void)        setAccumulator: (double) value
027 {
028     accumulator = value;
029 }
030 
031 -(void)        clear
032 {
033     accumulator = 0;
034 }
035 
036 -(double)    accumulator
037 {
038     return accumulator;
039 }
040 
041 -(void)        add: (double) value
042 {
043     accumulator += value;
044 }
045 
046 -(void)        subtract: (double) value
047 {
048     accumulator -= value;
049 }
050 
051 -(void)        multiply: (double) value
052 {
053     accumulator *= value;
054 }
055 
056 -(void)        divide: (double) value
057 {
058     accumulator /= value;
059 }
060 
061 @end
062 
063 
064 int main (int argc, const char * argv[])
065 {
066     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
067     double        value1, value2;
068     char        operator;
069     Calculator    *deskCalc = [[Calculator alloc] init];
070     
071     NSLog(@"Type in your expression_r.");
072     scanf("%lf %c %lf", &value1, &operator, &value2);
073     
074     [deskCalc setAccumulator: value1];
075     
076     switch (operator) {
077         case '+':
078             [deskCalc add: value2];
079             break;
080         case '-':
081             [deskCalc subtract: value2];
082             break;
083         case '*':
084             [deskCalc multiply: value2];
085             break;
086         case '/':
087             if (value2 == 0)
088                 NSLog(@"Division by zero.");
089             else
090                 [deskCalc divide: value2];
091             break;
092         default:
093             NSLog(@"Unknown operator.");
094             break;
095     }
096     
097     NSLog(@"%.2f", [deskCalc accumulator]);
098     [deskCalc release];
099     
100     [pool drain];
101     return 0;
102 }

最终输出结果:

Type in your expression_r.

178.99 - 326.8

-147.81


 

Type in your expression_r.

2012 / 0

Division by zero.

2012.00


编写 switch 语句时,应该记住任何两种情况的值都不能相同。然而,可以将多个情况的值与一组程序语句关联起来。简单地在要执行的普通语句之前列出多个情况的值就能实现该任务,不过每种情况中值的前面都使用关键字 case,而且后面要有一个冒号

作为一个例子,在以下 switch 语句中:

switch (operator)
{
      ...
    case '*':
    case 'x':
        [deskCalc multiplay: value2];
        break;
      ...
}

如果 operator 等于星号或是小写字母 x,将执行 multiply: 方法。




http://union.vancl.com/adpic.aspx?w=560&h=80
阅读    收藏 
标签:

限时免费

freeappaday

faad

软件营销

应用推广

分类: App推广实战密码

此文已在CocoaChina首页推荐,同时在App推广讨论区加精,感谢ga大等CocoaChina编辑的抬爱!



     苹果开发者Mike已在前文免费App的巨大吸引力中,就免费推广策略所针对的用户心理做了初步的分析。用户反正觉得不下白不下,而一旦白用白玩之后,就产生了改变使用习惯的可能性,开发者就多了一个潜在用户,抓住了后续销售的可能。那如何刺激免费产品的下载,达到最大限度的影响力呢?限时免费就是最佳的手段,没有之一。在做限免活动时,我们需要注意以下细节:


     软件的市场定位

     如果你准备进行限时免费的软件,只是针对一些利基市场的小众应用,那么象FreeAppaDay(FAAD)这样大型的推广网站一般不会接受这样的合作请求。而通过那些自动侦测价格变化的网站,在有限的时间内找到尽可能多的目标用户难度也是不小。一般而言,简单易上手的游戏,经典耐玩的游戏,社会化应用,实用的工具性应用或者近期很潮很热的应用类型都具备市场定位上的先天优势。


     软件的质量

     免费推广的最大风险就在于,免费产品给予用户最初体验,极大降低用户接受的门槛,但同时也就成为软件质量的试金石。好的免费应用容易让用户转换品牌,不好的初次体验也就意味着再也没有机会获得这个用户。所以在发展可以用于限时免费的软件时,一定不要觉得反正也是免费,就弄一些低质的东西糊弄用户。越是免费,质量越是要做到最好,千万不能出现一些低级的Bug或者Crash。


     在什么时间免费

     如果你的软件是开发来为上班族在工作中使用的辅助软件,那么选择在周末免费将是个糟糕的决定,这意味着很多潜在用户这时候都处于周末休假,等他们回来的时候,你的免费信息已经无法传递到目标受众了。如果你的应用是个节日气息浓厚的产品,那自然应该围绕节日打提前量。如果以上这些情况都不是,那么不要选择在周一。从大家的每周报表中都可以看到同样的规律,周一销售最差,周二开始逐渐回升,一般情况下,周末都是每周销售的高点。原因何在?很简单,星期一综合症。刚刚结束周末的休假,重新回到学习和工作生活中的人们,对这刚刚开始的“漫长的一周”充满了不适应,上App Store消费的热情也不大。


     时间的潜在陷阱和解决方案

     如果你的产品针对的是中国市场,通过各种渠道告诉中国用户,该应用将在北京时间8号零时开始免费。而不幸的是,你在iTunesConnect里设置了自动到期改变价格,而它是按PST时间8号零时执行。换成我是不知情的用户,只会对开发商的信誉表示怀疑,认为这是个狼来的故事,再不去理会你以后发布的任何消息。正确的做法是手动修改价格,除了可以准确把控因为时差导致的问题,同时能避开苹果自身的潜在Bug,有的时候开发者后台设置的到期自动改变价格不会生效。这也是为什么大型的限免推广网站一般要求合作开发者手动修改价格。


     如何把限时免费的消息最大限度地传递出去?

     通过自动监测的限免网站到达潜在用户这只是个非常被动的手段,做为开发者你还应该主动出击,利用各种推广手法在短时间内产生足够的爆发力,来达到活动的最大影响力。例如:

     电子邮件营销,提前告知各大网站的编辑,我的某某软件即将在什么时间限时免费,它有什么特别的Features值得关注。编辑们都喜欢捕捉最新的消息,而且他可能刚好在找类似软件,你正好把产品特点告诉他,就会得到个不错的Review。即便几十封邮件只换来了个小站的新闻稿也是值得的,从它那里你至少可以获得一批用户。除了编辑你还可以把营销的对象直指终端用户,向之前积累下来的一些有邮件联系方式的用户发信,告知相关活动,至于怎样去合法地收集这些用户而不至于变成垃圾邮件骚扰,以后苹果开发者Mike会专题细说。

     官方信息发布,在自己的官方网站上提前发布限时免费的相关消息,既能充实网站内容,又能提高网站的关注度,还可以把消息发布出去,何乐而不为呢?

     广告联盟发布信息,比如Google AdWords注册送广告金50刀,利用一些关键字竞价来从搜索引擎获得即时的用户转换,推高软件在App Store上的排名。这样的PPC(Pay Per Click)广告是按点击付费的广告,只展示是不花钱的。类似的做法还有从AdMob已经赚取的广告收入中拨出一部分进行推广,并且有20%的红利。

     社会化网络推广,不要告诉我你没有Facebook和Twitter,不知道Digg和Flickr是何物,那么你的社会化网络推广就是一片空白!在现在这个web2.0的时代,要想实现信息的爆炸式推广,以上这些网站请经常登录,多多分享,培养帐号,养兵千日,用兵一时。病毒式营销从这里开始!

     软文营销,如果你的英文水平不错,那么可以自己写软文,去TouchArcade上的用户Review板块发,不过恕Mike直言,没有几个国内开发者写得地道的,文章一看到就知道是国人写的中国式英语。最好的解决方法是请老外写,在一些国外的威客网站上甚至几美元就能买到个地道的评论,很超值的!写好后怎么做不用我多说了吧。你如果觉得软文推广多花点钱也没问题,那登录ReviewMe这样的博客软文广告商,你出钱别人会写Review,在一些博客上发布出来。不过上面的文章一般比较客观,在谈论软件优点的同时,也可能狠批你的应用某些不尽如人意的地方,以笔者Mike的经验性价比不高,还是慎重起见为妙。

     专业站点推广,这里的专业站点包括两种含义,一种是根据设备分类,到TA这样的iOS应用专门讨论区,进行活动信息的发布和推广。另一种则是根据你的应用定位,比如你开发了一款英语学习的软件,那你可以到潜在用户聚集的大型英语论坛去发帖。


     专业的限时免费网站

     和专业网站合作,利用它们既有的推广渠道,让你的应用排名火速升空。以最大的站点FAAD为例:

     FAAD的联系方式:Stacy Kramer, VP of Marketing stacy@icsmobile.com
                             Jen Loveridge, Senior Account Manager jen@icsmobile.com

     基本的流程大概是这样:

     第一步,与编辑联系确认合作方法。收入分成或是固定费用,Main Feature还是Daily Double。如果是收入分成,则根据免费推广转收费的30天收益来按比例付费给FAAD。百分比是开始推广前谈好的。如果是固定费用。则根据免费的时间和你和他们讨价还价的结果决定。Main Feature的话比较给力,Feature后的第二天还能有当天Daily Double的位置,而且会在一个月内展示在网站中部,效果蛮不错的。只是Daily Double的话,影响力有限,建议无论如何使用收入分成。下面的流程就以常用的收入分成流程为例,进行介绍。

     第二步,签署并交换合同,E-Mail或传真均可。将要推广应用的相关材料发给FAAD,要哪些材料他们会在邮件里提到,遵照邮件中给的Google文档所列内容准备。同时他们会告知你要在哪一天的PST时间几点修改价格,一般在你被Feature的前一天中午手动改为免费,这里说的都是美国PST时间。

     第三步,开发者按照约定修改价格,和添加FAAD要求添加的tagline在你的应用最上方,向用户表明你参与了FAAD的限时免费推广。活动正式开始。

     第四步,免费大概一周时间,具体软件可能出现不同,如果美国区Top Free前几的话,一般会让你延长几天的免费时间,然后手动改为收费。软件的价格,他们的编辑一般建议你定为0.99刀,最大限度地提升软件排名。

     第五步,到了30天期满的时候,你将得到一份报表,告知你应付给FAAD多少钱。

     同类网站对比,截止Mike发稿时:

     http://www.freeappaday.com/
     PR 5  Alex排名:34979    一般能冲入Top Free 美国前15

     http://freegameoftheday.com/
     PR 5  Alex排名:410728   背靠OpenFeint好乘凉,一般来说参加推广的是加入OpenFeint联盟的游戏。

     http://www.freeappcalendar.com/
     PR 4  Alex排名:335921  价格便宜,效果嘛也比FAAD差。性价比还是可以的。

     更多的类似dailyappdream.com这样的小站,大家可以如法炮制,自己发掘下。



http://union.vancl.com/adpic.aspx?w=660&h=70
阅读    收藏 
标签:

objective-c

整型值

浮点值

转换

类型转换运算符

分类: Objective-C表达式
要想在以后更有效地开发Objective-C程序,就必须理解整型值浮点值之间进行隐式转换的规则。下面的范例4-5表明数值数据类型间的一些简单转换。

01 // Basic conversions in Objective-C
02 
03 #import <Foundation/Foundation.h>
04 
05 int main (int argc, const char * argv[])
06 {
07     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
08     float    f1 = 123.125, f2;
09     int        i1, i2 = -150;
10     
11     i1 = f1;                // floating to integer conversion
12     NSLog(@"%f assigned to an int produces %i", f1, i1);
13     
14     f1 = i2;                // integer to floating conversion
15     NSLog(@"%i assigned to a float produces %f", i2, f1);
16     
17     f1 = i2 / 100;            //integer divided by integer
18     NSLog(@"%i divided by 100 produces %f", i2, f1);
19     
20     f2 = i2 / 100.0;        //integer divided by a float
21     NSLog(@"%i divided by 100.0 produces %f", i2, f2);
22     
23     f2 = (float) i2 / 100;    //type cast operator
24     NSLog(@"(float) %i divided by 100 produces %f", i2, f2);
25     
26     [pool drain];
27     return 0;
28 }

最终输出结果:

123.125000 assigned to an int produces 123

-150 assigned to a float produces -150.000000

-150 divided by 100 produces -1.000000

-150 divided by 100.0 produces -1.500000

(float) -150 divided by 100 produces -1.500000


在Objective-C中,只要将浮点值赋值给整型变量,数字的小数部分都会被删节。因此在范例11行,把f1的值指派给i1时,只有整数部分被存储到i1中。

范例14行,把整型变量指派给浮点变量的操作不会引起数字值的任何改变。

范例17行,由于是两个整数的运算,按照整数运算规则,结果的任何小数部分都将删除。

范例20行,一个整数变量和一个浮点常量。在Objective-C中,任何处理两个值的运算如果其中一个值是浮点变量或常量,那么这个运算将做为浮点运算来处理。

最后一个除法运算,范例23行,我们看到如何在声明和定义方法时将类型放入圆括号中来声明返回值和参数的类型。为了求表达式值,类型转换运算符将变量i2的值转换成float类型。该运算符永远不会影响变量i2的值;它是一元运算符,行为和其他一元运算符一样。因此表达式-a永远不会影响a的值,表达式(float)a也不会影响a的值。

优先级上,类型转换运算符比所有算术运算符的优先级都高,但一元减号运算符除外。下面再举个类型转换运算符的例子:

(int) 29.55 + (int) 21.99

再Objective-C中等价于 29 + 21

类型转换运算符通常用于将一般id类型的对象转换成特定类的对象。例如:

id myNumber;
Fraction *myFraction;
  ...
myFraction = (Fraction *) myNumber;

将变量myNumber的值转换成一个Fraction对象。转换结果将指派给Fraction变量myFraction。

笔者Mike在CSDN上传了范例4-5链接,欢迎大家下载。Basic_Conversions



http://union.vancl.com/adpic.aspx?w=560&h=80
阅读    收藏 
标签:

interface

implementation

program

分数

objective-c

分类: Objective-C面向对象
谈过了对象,实例和方法这些基本的面向对象概念后。接下来不妨定义个实际的类,并学习如何使用类的实例。进而领略Objective-C摄人心魄的秩序和美丽。

范例3-1,下面是一个简单的处理分数的程序:

01 // Simple program to work with fractions
02 #import <Foundation/Foundation.h>
03 
04 int main (int argc, const char * argv[]) {
05     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
06     int numerator = 1;
07     int denominator = 3;
08     NSLog(@"The fraction is %i/%i", numerator, denominator);
09     
10     [pool drain];
11     return 0;
12 }

在这里,分数是以分子和分母的形式表示。创建自动释放池后,main中的前两行将变量numerator和denominator都声明为整型,并分别给它们赋值1和3,最终显示他们。似乎问题都解决了,不过试想如果程序现在需要处理的不是一个分数,而是多个。那么这种简单的过程性编码将遇到麻烦。每次要引用分数的时候,都必须引用相应的分子和分母,而且更进一步的处理也会更加复杂。

最终输出结果:

The fraction is 1/3



那么接下来,我们何不把一个分数定义成单个实体,用单个名称(例如myFraction)来共同引用它的分子和分母。
范例3-2,用一个名为Fraction的新来重写3-1中的函数:

01 // Program to work with fractions - class version
02 
03 #import <Foundation/Foundation.h>
04 
05 //---- @interface section ----
06 
07 @interface FractionNSObject
08 {
09     int numerator;
10     int denominator;
11 }
12 
13 -(void)        print;
14 -(void)        setNumerator: (int) n;
15 -(void)        setDenominator: (int) d;
16 
17 @end
18 
19 
20 //---- @implementation section ----
21 
22 @implementation Fraction
23 
24 -(void) print
25 {
26     NSLog (@"%i/%i", numerator, denominator);
27 }
28 
29 -(void) setNumerator: (int) n
30 {
31     numerator = n;
32 }
33 
34 -(void)setDenominator: (int)d
35 {
36     denominator = d;
37 }
38 @end
39 
40 
41 //---- program section ----
42 
43 int main (int argc, const char * argv[])
44 {
45     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
46     Fraction *myFraction;
47     
48     // Create an instance of a Fraction
49     
50     myFraction = [Fraction alloc];
51     myFraction = [myFraction init];
52     
53     // Set fraction to 1/3
54     
55     [myFraction setNumerator: 1];
56     [myFraction setDenominator: 3];
57     
58     // Display the fraction using the print method
59     
60     NSLog(@"The value of myFraction is:");
61     [myFraction print];
62     [myFraction release];
63     
64     [pool drain];
65     return 0;
66 }

从代码中我们可以看到,整个程序在逻辑上分为3个部分:
@interface部分
@implementation部分
program部分

@interface部分用于描述类,类的数据成分以及类的方法;
@implementation部分包括实现这些方法的实际代码;
program部分包含实现程序目的的程序代码。

下面具体介绍每个部分

@interface部分

定义新类时,必须做一些事情。
首先,要通知Objective-C编译器这个类来自何处。换句话说,我们必须命名它的父类。
其次,确定这个类对象要存储的数据类型。就是说,必须描述类成员将包含的数据。这些成员被称为实例变量
最后,定义在处理该类的对象时将要用到的各种操作或方法的类型

以上工作都在程序中名为@interface的特殊部分内完成。

一般的@interface格式:

@interface NewClassName: ParentClassName
{
memberDeclarations;
}

methodDeclarations;
@end

按照约定,类名以大写字母开头!这样做的好处是其他人在阅读你的程序时,仅仅通过观察第一个字母就能把类名和其他变量类型区分开来。那除了类名,在Objective-C中制定名称的基本规则是什么?答案是:名称必须以字母下划线(_)开头,之后可以是任何(大写或小写)字母,下滑线或者0到9之间的数字组合。不过存在少数的特例,就是被系统使用的保留字无法使用,比如int。

讲了这么多,回过头来看下本例中的情况。
newClassName 为 Fraction (新类)
ParentClassName 为 NSObject (父类)
memberDeclarations (数据类型) 不再复述。唯一需要注意的是每次创建新的对象时,将同时创建一组新的实例变量,而且是唯一一组。因此如果拥有两个Fraction,一个名为fracA,另一个名为fracB,那么每个都将有自己的一组实例变量。
methodDeclarations (方法类型) 
由于你不能直接访问分数的内部表示(就是,直接访问它的实例变量),因此你必须通过定义各种方法才能使用它。

-(void) print;

开头的负号(-)通知编译器,该方法是一个实例方法。如果是加号(+),则表示是类方法。类方法之前有提过就是对类本身执行某些操作的方法。例如创建类的新实例。好比制造厂制造一辆新的汽车。在这里汽车是个类;而要造新汽车便是类方法。

言归正传,实例方法对类的特定实例执行一些操作。例如设置值,检索值和显示值等。声明方法print时,必须通知Objective-C编译器这个方法是否返回值。void代表无返回值,如果是int表示返回整型值,double则返回双精度值,以此类推。当返回值定义了void后。就无需在方法结尾执行一条return语句了,因为return就是为了返回特定的值而存在。

再看@interface中还声明了其他两个方法:

-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;

它们都是不返回值的实例方法。每个方法都有一个整型参数,就是通过参数名前面的(int)指明的。就setNumerator来说,其参数名是n。这个名称可以是任意的,它是用来引用参数的方法名称。总结下声明这两个方法的语法。每个方法名都以冒号结束,这个冒号通知编译器该方法期望看到一个参数。然后,指定参数的类型,并将其放入一对圆括号中,这与方法指定返回值的类型非常相似。最后,使用象征性的名称来确定方法所指定的参数。整个声明以一个分号结束。

- 实例方法
(void) 返回值类型为无返回值
setNumerator 方法名
: 该方法期望看到一个参数
(int) 参数的类型为整型值
n 象征性的名称来确定方法所定的参数

@implementation部分

在@interface所声明的方法,在@implementation定义。所谓定义就是给出实际的代码。

一般的@interface格式:
@implementation NewClassName
methodDefinitions;
@end

NewClassName表示的名称与@interface部分的类名相同。可以在其后使用冒号加上父类名称。
例如:@implementation Fraction: NSObject
不过要声明的是它是可选的,而且通常并不这么做。

在代码中,print方法使用NSLog显示变量numerator和denominator的值。setNumerator和setDenominator将参数储存到各自的实例变量中去。

program部分

在这个部分中,包含了解决特定问题的代码

Fraction *myFraction;
定义了一个名为myFraction的对象。其中的星号(*)是必须的,它实际表示myFraction是对Fraction的一个引用(或者指针)。

myFraction = [Fraction alloc];
alloc 是 allocate 的缩写,因为要为新分数分配内存存储空间。表达式[Fraction alloc]向Fraction类发送一条消息。请求使用来自父类NSObject的alloc方法。使用方法的结果就是获得该类的新实例。把返回值储存在myFraction中。

myFraction = [myFraction init];
alloc方法保证对象的所有实例变量都变成初始状态。然而,这并不意味着该对象进行了适当的初始化进而可以使用。在分配对象后还必须进行初始化,init方法用于初始化类的实例变量,同样源自继承来的父类NSObject。现在,我们正将init消息发送给myFraction。就是说,要在这里初始化一个特殊的Fraction对象,因此它没有发送给类,而是发送给类的一个实例。把返回值储存在myFraction中。

由于这两条代码在Objective-C中非常常见。通常程序员都使用它们的组合形式:
myFraction = [[Fraction alloc] init];
和算数运算法则一样,内部的[Fraction alloc]首先求值,再应用init方法。初始化的过程一次性完成后把结果赋值给myFraction。

做为最终的简写形式,经常把分配和初始化直接合并到声明行,如下所示:
Fraction *myFraction = [[Fraction alloc] init];
而这种风格的延伸,将会在以后的代码中更经常被看到:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
此处将alloc消息发送给NSAutoreleasePool类,请求创建一个新实例。然后向新创建的对象发送init消息,以初始化该对象。

剩下的代码就非常简单了,不再多说。

代码最终输出结果很简单,不过我们已经在用面向对象的思想来处理却是个质的飞跃!

The value of myFraction is:

1/3


最后分享下笔者在CSDN上传的源代码链接:Simple_Fraction (范例3-1) Fraction_Class (范例3-2)


 



http://union.vancl.com/adpic.aspx?w=560&h=80

 

阅读    收藏 
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有