Consumable苹果新加坡的标志居然是红苹果 http://twitpic.com/p7v5b
苹果允许在免费应用中提供购买(In-App Purchase)之后,销售模式有了全新的改变,用户们终于可以先试后买了。以后那些几个漂亮图+烂内容,用户卖完大呼上当的程序恐怕越来越没有市场了。
正好apple组织了一个In-App Purchase的培训,来瞧瞧,顺便跟开发者们交流一下。迟到了几分钟,百人小会议厅已经坐满了,茶歇的时候才发现,居然有一半洋人,很多人一身休闲打扮,穿着短裤,踏着拖鞋就来了。培训先介绍In-App Purchase,然后演示了一个具体的例子。只有一个感觉,非常的复杂。
In-App Purchase的3种类型
- Consumable:一次性购买,最简单的类型,不用保存历史记录。
- Nonconsumable:每个产品,用户只买一次,此后就可以在自己的所有设备上看到该产品。
- Subscriptions:订阅模式允许多次购买末一个产品,但是购买后,用户可以在自己的所有设备上看到该产品。
一个典型的In-App Purchase需要4大部分的协作:your Server,App,App Store,iTune。
Your Server主要是保存交易代号,传递购买的内容;当然如果购买的内容比较简单,Server也是可以省略的。
App中内置需要购买的产品

用自己的服务器来提供需要购买的产品

后面还有一些话题,获取产品信息,在程序中添加购买的过程,向App Store验证交易收据,在iTune Connect中的配置,使用测试帐号来测试程序的购买过程等等,都很实用。
开发iPhone应用已有月余,今天早晨发现,一个程序终于杀入了日本app store的分类Top 25了。昨天还没进前30的时候,销量就已经翻倍了,今天的销量想必会有惊喜。这个程序开发只用了2天,看来成功与否跟花的时间多少并非成正比,对用户需求的把握才是最重要的。
这个趋势图是用unfish开发的AppStoreReporter弄出来的,可以导入和保存所有历史销量,然后图表显示,非常实用,强烈推荐。
这一个月的销量节节攀升,说明iPhone开发还是有利可图的,当然策略要对头,我还是会坚持每个开发不超过一周的原则,因为时间一长,要么坚持不下,要么销量不好,白白浪费时间。
业余创业一般分为两个阶段:第一阶段起步,目标就是活着,收入稳步上升说明创业思路对头,另外预期也会随着逐渐上升,在心里上可以避免大起大落;另外,由于是业余时间搞的,每个应用程序的开发周期要严格控制在很短的时间,如果效果不好,坚决砍掉。
当收入稳定在某个级别,足以让你衣食无忧的过几年的时候,就可以考虑放手一搏了,这时候在市场上也有经验了,对客户的需求有了深刻的了解,尝试做一些大型的应用,也可以对已有的销量较好的应用进行重点升级。
经过15天的苦苦等待,第一个iPhone程序终于登录app store了,不过现在只是在US的app store中,其他地方的store虽然还看不到,但是查询的时候却可以查到公司名,就是没有app,很奇怪!
查了一下状态,还在Review中,平均12天的提交进程,果然名不虚传。提交后发现了一些问题,特别是程序不稳定,使用一段时间就退出。不过也懒得reject Binary了,还得重新排队,也许测试人员那里没问题就进去了,然后再升级吧。9月上半月,争取再提交10个app。
简单列一下提交过程:
第一步交钱,个人开发者,每年99刀,使用非中国地区,省了fax的麻烦,直接在app store就可以使用信用卡付款。不过,过程也是一波三折,发给我确认码之后,居然提示已被锁定,联系客服之后才解决。
第二步登录,进入iPhone Developer Program Portal。依次设定Team,请求Certificate,确认开发用Device,申请App ID,获取Provisioning,生成Distribution。Potal中都有详细的说明和步骤,不难,就是麻烦。
第三步,在iTunes Connect中提交签名过的app,进入漫长的等待review的过程。
进军iPhone开发计划执行顺利,3天过后,程序完成,说明文档,图片也准备好了。只是注册iPhone开发帐号遇到了问题,不小心使用中国的信用卡注册,结果到了最后一页,才说中国没有开通App Store,无法接受信用卡,只能手填一个表格,然后fax给美国,交钱居然还这么麻烦。奇怪,接受个信用卡,跟App Store有什么关系?在线收款自己做不了,可以外包嘛。苹果的设计还真有点问题,居然没有后退按钮,所以无法改其他国家,只能联系他们的support来重置一下。预计明天能搞定,然后就可以提交程序了。
再列几个实用资源
http://code.google.com/p/cookbooksamples/downloads/list 《the iPhone developer’s cookbook》的源代码。里面最人性化的是有mov格式的视频,这样不用编译执行源代码,直接看看视频就知道是不是自己需要的。
http://www.cocoachina.com/bbs/read.php?tid-568.html G大总结的FAQ,非常实用。
http://thierryxing.javaeye.com/blog/453645 thierryxing翻译的《如何创建你的第一个iPhone程序》,一步一步很详细。
从几个月前开始学Objective C开始,断断续续也写了几个iPhone小程序了。一直想写一个复杂点的游戏,无奈,时间都花在了向往已久的巴厘岛和普吉岛。计划一次次的流产,再不发布,就成纸上谈兵了。这个周末,决定利用3天时间写出一个先,不需要太复杂,毕竟复杂度和赚钱是两回事,找一个简单点的题材开刀,先睹为快。
用在线脑图利器MindMeister写了个开发计划

截止到现在,一切按照计划,正在攻克技术问题中。
整理了一下手中的iPhone开发网站、论坛和博客,精选了这10个常去的网站。其中有2篇教学文章,由于非常经典,于是单列出来,与其网站并列。本文的短网址为 http://bit.ly/3llz7
建议新入行的朋友在看教学文章的同时多上论坛,与大家交流,偶尔看看别人的自曝,自己也会信心倍增。另外,实践最重要,首先行动起来。
http://cocoachina.com/ 大量iPhone开发资料,教学,经验,还有自曝。
http://www.javaeye.com/forums/board/mobile iPhone开发论坛,人气鼎盛,大量自曝,还有Android的讨论
http://developer.apple.com/iphone/ 苹果iPhone开发官方主页,提供大量实例、文档和教学视频
http://www.stanford.edu/class/cs193p/ 斯坦福大学的iPhone课程,2009年4~6月,有pdf和视频下载
http://bit.ly/RuaKq 飞机游戏iFighter的作者dr_watson写的iPhone游戏开发经典教学系列,有源码
http://www.iphoneside.com/ iPhone达人的博客,很多有价值的资源下载,新闻和教程
http://lichen1985.com/blog/ iPhone应用的作者,雨雪霏霏的iPhone博客,很多开发手记和心得
http://blog.liuhongwei.cn/category/iphone/ iPhone开发博客,提供教学文章,经验分享,还有GAE
http://www.javaeye.com/topic/422948 iPhone日本市场高手的自曝贴,第1个月就赚了2千刀,大量详细的数字和图片
http://dev.iphonetw.net/ 台湾iPhone开发者论坛,有些教学文章和讨论
Objective C 快速入门诗
C没有类
这让人很疲惫
对象的说法很时髦
不就是继承封装组合人人会
右走是C++,这个大众都熟悉它
左走就是objective-c,躲在僻静僻静的麦金塔
本是同根生的C
如何高举面向对象的大旗
求同存异标新立异且听一一细分清
对象的C
是不同的C
类的处理与众不同重点要区分
不重复是我的口头禅
任何时候我只说一次告诉你我的地盘
[@begincommand] | @end就是我的指示
@interface classname 声明类
@implementation classname 实现类
@protocol interfacename 声明接口
就是这么简单,你的一定要明白
我先声明对成员变量和方法的关系有远近
成员变量大大括在我的怀
关系远近 public / protected / private 来区分
若不声明全默默受着保护
静态成员变量请不要放在此
成员方法我不太爱
前面拴着绳子置于类的变量列表外
减号就是普通函数
加号就是静态函数莫怪
函数的声明有点怪
我要一眼叫出名,包括函数名和参数名
其余的类型括起来,我有空再来慢慢看
函数名和参数名之间用:分隔开
多个参数的函数那就是更怪
逗号其实不是我的爱
后续的每个参数分隔用空白
每个参数形式如 标签:(参数类型)参数名
其实只要把函数名看作是第一个参数标签
你就能领悟其中的奥妙并在调用时喜爱
成员方法太多我才懒得区分亲疏远近
它们一律都是公之于众要好好的干活
谁若不服胆敢出头犯上
就踢出头文件打入冷宫永世不能露面试试看
所有的成员方法都是虚函数
改则重载,不改就继承
不用任何标记请放心大胆随便使用
对象的类,在继承层次上考虑才显得重要
所有的类最终都继承于NSObject
因为它给你创建自己生命的方法
不继承于NSObject的只能是接口protocol
它没有成员变量只有方法
它只有声明不用实现
这点和java很相似
当然类还有一些绝活可以让你开开眼
可以动态的扩充一个类 而不总是用继承
@interface CClassA(Category)|@end
@implementation CClassA (Category)|@end
源代码外包含该 类的头文件
就可以使用该Category中的方法
也可以动态的替换一个类
但是只限于用继承类来替换基类功能
[CInheritClass poseAsClass: [CBaseClass class]];
声明之后用基类创建的对象实际上行为都是继承类
所以一个类的完整声明如下:
@interface CClassA(Category): CBaseClass<IA,IB...>
类别,基类,接口一一具全
加上静态 虚函数
所有特性和C++均可对应
再加上所独有的特性
这一特性编译类语言很少有
设计得当完全可以实现动态调用dll切换功能
类的定义和使用,也有点怪
想想看一个对象的生命周期,该是如何办
创建很是别扭
这样就定义了一个类对象,
CClassName* pA = [[CClassName alloc] init];
能且只能返回对象指针
释放分为两种
自动释放声明后 [pA autorelease]; 以后可以不管
否则就必须配对 [pA release];
注意类的构造函数init可以捕获
但是析构函数却没有这点很让人意外
使用类也有多种情况
调用成员方法用中括号 int nRtn = [pA method:param1];
而静态成员方法不需要对象 int nRtn = [CClassName method];
调用成员变量还是C格式 pA->m_nCount = 1;
所有的类,都可以对应一个id类型
用来引用一个对象 id cur = sq;
或者用来引用一个对象指定的接口 id<IA> cur = sq;
然后就可以调用该对象的方法和指定接口方法
Iphone APP程序结构
在Objective C入门中我们了解了如何定义类,类的实现,以及调用类函数的方式。现在再来看一看关于类的高级概念。
id,动态绑定
#import <stdio.h>
#import "Bank.h"
int main( int argc, const char *argv[] ) {
Bank *bank1= [[Bank alloc] init];
Bank *bank2= [[Bank alloc] init];
id b; //可以把任何对象赋值给b
[bank1 addAmount: 1];
b = bank1;
[b print]; //调用bank1的print函数
b = bank2;
[b print]; //调用bank2的print函数
// true
if ( [bank1 isMemberOfClass: [Bank class]] == YES ) {
printf( "bank1是Bank类的一个对象\n" );
}
// true
if ( [bank1 respondsToSelector: @selector( addAmount: )] == YES ) {
printf( "bank1响应addAmount:函数\n" );
}
// free memory
[bank1 free];
[b free];
return 0;
}
id类型可以接受各种类型的对象,然后调用对应的函数。调用函数时,Objective C在编译的时候并不会检查该对象是否有该函数,需要开发人员自己确保调用的有效。另外Objective C也提供功能,在运行时检查某对象是否具有某函数。
类的高级使用:继承、类别、扮演、协议
////////////// BankMath.h
#import "Bank.h"
@interface Bank(Math) //为类Bank定义一个类别Math
-(void) add: (int) b; //Math中的函数add
-(void) sub: (int) b; //Math中的函数sub
@end
@protocol Auditable //定义一个协议
-(void) audit; //其中包括一个函数audit的定义
@end
@interface ExBank: Bank<Auditable> //ExBank类继承Bank,同时实现Auditable协议
-(void) print; //定义一个新的函数print,覆盖父类Bank中的print函数
@end
////////////// 实现部分 BankMath.m
#import "BankMath.h"
@implementation Bank (Math) //Bank的类别Math的实现部分
-(void) add: (int) f {
amount ++;
}
-(void) sub: (int) f {
amount --;
}
@end
@implementation ExBank
// 实现新定义的函数print
-(void) print {
printf("ExBank amount=%i", amount);
}
// 实现协议中包含的函数audit
-(void) audit {
printf("audit: amount=%i", amount);
}
@end
////////////// main.m
#import <stdio.h>
#import "Bank.h"
int main( int argc, const char *argv[] ) {
Bank *bank = [[Bank alloc] init];
[bank add: 10]; //直接使用Bank对象类别Math中的函数
[bank sub: 5]; //直接使用Bank对象类别Math中的函数
[bank print];
[ExBank poseAsClass: [Bank class]]; //使用ExBank来扮演Bank
Bank *bank2 = [[Bank alloc] init]; //对Bank的调用,就是对ExBank的调用
[bank2 print]; //调用ExBank的print函数
[bank2 audit]; //调用ExBank的audit函数
id auditable = bank2; //为auditable赋值bank2
[auditable audit]; //调用bank2的函数audit
//[auditable print]; //不行,因为Auditable类型中没有该函数
[bank free]; // 释放对象
[bank2 free]; // 释放对象
return 0;
}
-
类定义@interface,相当于Java和C++中的class
-
继承,与Java继承类似,没有C++中继承的那么多繁琐的访问范围差别
-
类别(categories),是用来扩展类的好办法,比继承更方便,因为你不需要有源代码就可以扩充某个类。
-
扮演(Posting),可以在运行时指定用某个类A来替代另一个类B,这样此后所有对B的调用都是对A的调用。
-
协议(@protocol),相当于Java的接口,或C++的abstract class。定义在其中的函数只有定义而不需要实现。使用协议的时候,一个类可以实现多个协议,多个协议之间用逗号分隔列出。
进军iPhone开发,最大的难点之一就是怪异的Objective C语法了。不过,了解之后才发现,原来仅仅是形式上与C++、Java有差异,属于换汤不换药。如果有C语言基础,又用过C++、Java,2天之内掌握Objective C,没有问题,至少看例子程序会感觉顺眼很多。
Objective C脱胎于C语言,苹果版的开发编译环境就是大名鼎鼎的Xcode,其中的Cocoa就是Objective C库函数。
与C语言一致的部分
int main( int argc, const char *argv[] ) {
printf( "hello worldn" );
return 0;
}
- 数据类型,表达式,各种运算符
- 循环:for, while, do while, break, continue
- 分支:if, else, switch
类定义@interface
#import <Foundation/NSObject.h>
@interface Bank: NSObject {
NSString *name;
int amount;
}
-(void) print;
-(void) addAmount: (int) a;
-(int) amount;
-(Bank *) initWithName: (NSString *) n andAmount: (int) a;
@end
- 写在Bank.h中
- #import是引入库函数
- @interface是表明定义了一个类,冒号后面是父类类型
- 两个大括号之间的部分就是类的成员变量,只有类函数能够直接访问
- - 表明要定义一个类对象级别的函数;如果是+,表明要定义类级别的函数
- 返回值与参数的类型放在()内
- 函数定义中的: 表明后面会跟一个参数
- 如果函数有多个参数,要写多个xxx:
- 类的函数定义结束后,使用@end关闭
类实现@implementation
#import "Bank.h"
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
@implementation Bank
-(void) print {
printf("Total amount is %i", amount);
}
-(void) addAmount: (int) a {
amount += a;
}
-(int) amount{
return amount;
}
-(Bank *) initWithName: (NSString *) n andAmount: (int) a{
self = [super init];
name = n;
amount = a;
return self;
}
@end
- 写在Bank.m
- @implementation定义函数的具体内容,后面接着类名
- 函数头按照定义来写
- 最后用@end来结束所有函数体
调用写好的类和类函数
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import "Bank.h"
int main( int argc, const char *argv[] ) {
//创建新对象,使用缺省初始化函数
Bank *bankDefault = [[Bank alloc] init];
//创建新对象,使用自定义初始化函数
Bank *bank = [[Bank alloc] initWithName: @"Harry" andAmount: 28];
[bank addAmount: 1];
[bank print];
[bank free]; // 释放对象
[bankDefault free]; // 释放对象
return 0;
}
- 调用类函数的时候,首先创建并初始化对象。这里我们使用缺省的init和我们自定义的initWithName来分别初始化一个对象;
- 使用[]来调用函数,按照次序分别是:对象名,函数名,: 参数值(如果有),函数名第二部分(如果有),:第二参数值(如果有);
参考: