苹果应用onc苹果se拍照效果果怎么样

苹果 应用程序内购 实现全攻略
刚在/iphonedev/sdk/35.html&看到这篇介绍iap开发的文章,感觉很详细.
IAP能正常工作的秘诀:分成两个步骤:
创建及提取产品描述
第一个步骤是你可能遇到问题的部分。一旦你在代码中成功地获取了产品描述,编写购买产品的代码不过是小菜一碟。
我们先看看步骤1。
创建及提取产品描述
下面是有关创建产品及提取其描述的非常粗略的步骤:
创建唯一的App ID
生成及安装新的provisioning profile文件
在Xcode中更新 bundle ID 及 code signing profile
如果还没做的话,请在iTunes Connect中提交有关你程序的 metadata
如果还没做的话,请在iTunes Connect中提交你程序的二进制码
为IAP添加新产品
编写提取产品描述的代码
等待几小时
提取产品描述的代码非常简单,但其他步骤则很容易错。
注意: 为提取产品描述,你并不需要在iTunes Connect中创建IAP测试用户。
1. 创建唯一的App ID
为支持IAP,你的App ID不能包括通配符(“*”)。为确定你的App Id是否包括通配符,请登录/iphone,在 iPhone Developer Program Portal中选择左边菜单中的 “App IDs”检查你的 App ID。
下面是一个唯一的App ID:
.runmonster.runmonsterfree
下面不是一个唯一的 App ID:
.runmonster.*
如果你还没有一个唯一的App ID,按如下步骤创建一个:
在developer portal中的 App IDs 部分,选择“New App ID”
填写下列信息:
Display name(显示名): 选取一个不同的App ID的名称。你不能编辑或删除旧的App ID,所以你必须为你的App ID提供一个新名称以避免溷淆。
Prefix(前缀): 生成一个新的前缀,或者如果你的程序是通过Keychain Services API分享数据的系列程序中之一的话,则选用已存在的前缀。
Suffix(后缀): panyname.appname (这是通用格式 – 注意没有使用通配符)。
按 “Save”
按 App ID旁的“Configure” 链接
选取 “Enable In App Purchase”选择框
按“Done”
2. 创建一个新的Provisioning Profile文件
在创建了新的App ID后,你需要生成一个指向这个App ID的新provisioning profile。
下面就是令人痛苦的生成和安装新provisioning profile的详细步骤:
在 iPhone Developer Portal中, 选择左边的Provisioning部分
确保你处于Development 标籤下, 按下右上角的 “New Profile”
填入所需信息并指向你刚创建的唯一的App ID
如果你在Actions条目下看到 “Pending”,那麽请按下“Development”标籤标题进行刷新
点击 “Download” 下载新的profile文件
将profile文件拖入到Dock中Xcode图标上进行安装
如果你想在硬盘上保存provisioning profile,那麽你可以按如下步骤手工安装profile:
在Xcode中, 选择 Window & Organizer
选择左边 “Provisioning Profiles” 分类
Ctrl-按下profile & Reveal in Finder
将新profile拖入到 profile Finder 窗口
3. 更新Xcode 设置
在Xcode中安装了 profile 文件后,你需要对使用此provisiong profile的项目进行一些编辑工作:
编辑项目 .plist 文件使其 Bundle ID 与 App ID 匹配。忽略ID开始部分的字母数字序列。例如,在Developer Portal中你的App ID为“.runmonster.runmonsterfree”,那麽在Bundle ID中你只需输入“com.runmonster.runmonsterfree” 。
编辑项目的 target 信息以使用新的provisioning profile:
选取 Project & Edit Active Target
选取顶部“Build” 标籤
选取需要的 configuration (通常为 Debug)
在Code Signing Identity中选择新的provisioning profile
在Code Signing Identity之下的行中(可能名为 Any iPhone OS Device)选择新的provisioning profile
4. 添加你的应用程序
如果你的程序已经发表到App Store了,那麽可以略过此步骤。
在你将产品添加到 iTunes Connect之前,你必须添加此产品所需的程序。如果你的程序还没有100%完成也无需担心,你可以先提交具有部分数据的程序,最后再提交真实的程序。
注意: 只有 SKU 和 version(版本)部分是以后不可修改的
登录到 /iphone
点击右边链接进入 iTunes Connect
注意:你必须先登录到,否则会有不测发生(译者注:具体是什麽不测我也不太清楚,胆大的请自己试一下)
在 iTunes Connect主页点击 “Manage Your Applications”
在右上角点击“Create New Application”
填写程序所需的一切信息。当要求程序二进制码时,请选择稍后上传选项。
5. 提交程序二进制码
Apple的文档中没有任何地方提及详情,但它却是必须的步骤。要成功测IAP功能,你必须提交程序的二进制码。即使你的程序还没有100%完成,你仍然需要提交二进制码。然而,你也可以立即摈弃你的二进制码,使其不会进入审核阶段。
下面这些步骤非常关键,我可是因为少做了某些步骤而度过了一段非常痛苦的时间:
生成App Store发佈版程序
如果你不知怎麽做,请在 iPhone Developer Portal 中点击左方的 Distribution标籤,并选择 “Prepare App” 标籤。然后,根据蓝色链接的指示:
获取iPhone发行许可证
创建并下载在App Store发行所需的iPhone Distribution Provisioning Profile
在Xcode中生成程序的发行版
在iTunes Connect中进入程序页
选择 “Upload Binary”
上传.zip压缩程序
如果你的程序还没有100%完成以进行审核,那麽请点击iTunes Connect中你程序首页中的 “Reject Binary”链接。程序的状态应该更新为 “Developer Rejected”.
不用担心,由于程序的状态是“Developer Rejected”,Apple是不会对其进行审核的。你可以在任何时候提交程序的新版本并使其状态为“Developer Rejected”,这不会对以后程序正式提交的等待时间有任何影响。
6. 添加产品
完成了以上所有步骤后,我们最终可以向iTunes Connect中添加产品了。
确保登录到 /iphone
进入 iTunes Connect 主页
点击 “Manage Your in App Purchases” 链接
点击 “Create New”
选择你的程序
填写下列产品信息:
Reference Name(参考名称): 产品的通用名称。比如,我使用的是 “Pro Upgrade”。此名称是不允许进行编辑的,它不会显示于App Store中。
Product ID(产品ID): 你产品的唯一id。通常格式是 pany.appname.product,但它可以说任何形式。它并不要求以程序的App ID作为前缀。
Type(类型): 有三种选择
Non-consumable(非消耗品): 仅需付费一次 (例如你希望将出现从免费版升级为专业版)
Consumable(消耗品): 每次下载都需要付费
Subscription(预订): 循环反覆
Price Tier(价格等级): 产品价格。参见不同等级的价格列表。
Cleared for Sale(等待销售): 一定要选取此项,否则的话,测试时会发生非法产品ID的错误。
Language to Add(增加的语言): 选一项。下列两项将出现:
Displayed Name(显示名称): 用户看到的产品名称。比如我选择 “Upgrade to Pro”。
Description(描述): 对产品进行描述。此处输入的文本将与Displayed Name 及 Price 一起在你代码中提取 SKProduct时出现。
Screenshot(截屏): 展示你产品的截屏。儘管屏幕上会显示“提交截屏会触发产品审核过程”之类的文字(个人拙见,这是非常糟糕的设计),你还是可以安全地提交截屏而不会使产品进入审核过程。存储后,选择“Submit with app binary” (随程序二进制码一起提交)选项。是产品与程序二进制绑定在一起,所以在你最后正式提交100%完成的程序二进制码时,产品也会随之提交。
点击 “Save”
7. 编写代码
下面我们开始编写代码对刚加入到iTunes Connect中的产品信息进行提取。我访问产品数据,我们需要使用 StoreKit framework。
注意: StoreKit 无法在模拟器上工作。你必须在真机上进行测试。
1.添加 StoreKit framework 到你的项目中。
2.添加SKProduct引用到你的 .h 文件中:
// InAppPurchaseManager.h
#import &StoreKit/StoreKit.h&
#define kInAppPurchaseManagerProductsFetchedNotification @&kInAppPurchaseManagerProductsFetchedNotification&
@interface InAppPurchaseManager : NSObject &SKProductsRequestDelegate&
SKProduct *proUpgradeP
SKProductsRequest *productsR
注意: InAppPurchaseManager 是一个单例类,它处理程序中所有IAP任务。它是本文中的示例程序。
3.产品请求,并在相应.m文件中实现代理协议:
// InAppPurchaseManager.m
- (void)requestProUpgradeProductData
NSSet *productIdentifiers = [NSSet setWithObject:@&com.runmonster.runmonsterfree.upgradetopro& ];
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate =
[productsRequest start];
// we will release the request object in the delegate callback
#pragma mark -
#pragma mark SKProductsRequestDelegate methods
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
NSArray *products = response.
proUpgradeProduct = [products count] == 1 ? [[products firstObject] retain] :
if (proUpgradeProduct)
NSLog(@&Product title: %@& , proUpgradeProduct.localizedTitle);
NSLog(@&Product description: %@& , proUpgradeProduct.localizedDescription);
NSLog(@&Product price: %@& , proUpgradeProduct.price);
NSLog(@&Product id: %@& , proUpgradeProduct.productIdentifier);
for (NSString *invalidProductId in response.invalidProductIdentifiers)
NSLog(@&Invalid product id: %@& , invalidProductId);
// finally release the reqest we alloc/init’ed in requestProUpgradeProductData
[productsRequest release];
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
上面代码有几点需要注意:
指定产品id时,你必须使用完整产品id。例如,上例中使用 “com.runmonster.runmonsterfree.upgradetopro”。仅使用 “upgradetopro” 将不会正常工作。
如果在productsRequest:didReceiveResponse:中response.products 为 nil,而你的产品id出现于 response.invalidProductIdentifers 数组中时,那麽请做好心理准备开始一场徒劳的搜索战吧。 StoreKit API没有提供任何帮助,也没有任何指示关于为什麽你的id是无效的。很可爱,不是吗?
SKProduct类提供了有关程序标题和描述的本地化版本,但是价格则没有本地化版本。下面是针对此疏忽提供的代码:
// SKProduct+LocalizedPrice.h
#import &Foundation/Foundation.h&
#import &StoreKit/StoreKit.h&
@interface SKProduct (LocalizedPrice)
@property (nonatomic, readonly) NSString *localizedP
// SKProduct+LocalizedPrice.m
#import &SKProduct+LocalizedPrice.h&
@implementation SKProduct (LocalizedPrice)
- (NSString *)localizedPrice
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:self.priceLocale];
NSString *formattedString = [numberFormatter stringFromNumber:self.price];
[numberFormatter release];
return formattedS
加入上述代码,测试一下。你应该在控制台窗口中看见产品信息了。然而更大的可能是,你得到了一个无效的产品id。我下一篇文章将介绍怎样对这个问题进行调试。但是,下面的步骤8有可能是阻碍你前进的障碍。
8. 等待几小时
遵循了上述所有步骤,但是你的产品仍然是无效的?你是否两次,三次,四次不懈努力地确认你是否遵循了上面提到的每个步骤?你是否已经对网上IAP信息少得可怜而感到绝望?
那麽,你应该等待。
你的产品要进入iTunes Connect使得Apple准备好沙箱环境需要一些时间。对于我而言,我是经过了无数次产品无效错误的绝望。而在24小时后,我没有修改任何一行代码,但产品id变为有效。我认为要使产品发佈到Apple的网络系统需要几个小时的时间,但如果你有时间的话,你可以像我一样等上24个小时。
至此你应该已经成功地获取了 SKProduct 描述。比较而言,支持购买产品相对简单些。仅需下面三个步骤:
编写代码支持事务(transaction)
在iTunes Connect中添加程序测试用户
在设备中登录你的 iTunes Store 帐号
我们从编写支持事务所需代码开始。
1. 编写代码支持事务
首先注意:你将负责开发产品购买的用户界面。StoreKit 未提供任何与用户界面相关的元素。如果你希望你的购买用户界面与App Store一样,那麽你要自己完成。
下面所有代码都是有关事务处理的后台部分。这是一个单独的类只有一条简单的API以供外部类(比如view controller)调用进行购买。如果你找到将其集成到你程序的购买部分的方法,那麽我推荐你使用类似方桉。
首先,需要遵循 SKPaymentTransactionObserver 协议:
// InAppPurchaseManager.h
// add a couple notifications sent out when the transaction completes
#define kInAppPurchaseManagerTransactionFailedNotification @&kInAppPurchaseManagerTransactionFailedNotification&
#define kInAppPurchaseManagerTransactionSucceededNotification @&kInAppPurchaseManagerTransactionSucceededNotification&
@interface InAppPurchaseManager : NSObject &SKProductsRequestDelegate, SKPaymentTransactionObserver&
// public methods
- (void)loadS
- (BOOL)canMakeP
- (void)purchaseProU
上面我们定义了两个新的notification,它们将作为购买事务的结果被发送。在上例中我们仍然使用与获取产品描述同一个InAppPurchaseManager类。
// InAppPurchaseManager.m
#define kInAppPurchaseProUpgradeProductId @&com.runmonster.runmonsterfree.upgradetopro&
#pragma Public methods
// call this method once on startup
- (void)loadStore
// restarts any purchases if they were interrupted last time the app was open
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// get the product description (defined in early sections)
[self requestProUpgradeProductData];
// call this before making a purchase
- (BOOL)canMakePurchases
return [SKPaymentQueue canMakePayments];
// kick off the upgrade transaction
- (void)purchaseProUpgrade
SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId];
[[SKPaymentQueue defaultQueue] addPayment:payment];
#pragma Purchase helpers
// saves a record of the transaction by storing the receipt to disk
- (void)recordTransaction:(SKPaymentTransaction *)transaction
if ([transaction.payment.productIdentifier isEqualToString:kInAppPurchaseProUpgradeProductId])
// save the transaction receipt to disk
[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:@&proUpgradeTransactionReceipt& ];
[[NSUserDefaults standardUserDefaults] synchronize];
// enable pro features
- (void)provideContent:(NSString *)productId
if ([productId isEqualToString:kInAppPurchaseProUpgradeProductId])
// enable the pro features
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@&isProUpgradePurchased& ];
[[NSUserDefaults standardUserDefaults] synchronize];
// removes the transaction from the queue and posts a notification with the transaction result
- (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
// remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, @&transaction& , nil];
if (wasSuccessful)
// send out a notification that we’ve finished the transaction
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo];
// send out a notification for the failed transaction
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo];
// called when the transaction was successful
- (void)completeTransaction:(SKPaymentTransaction *)transaction
[self recordTransaction:transaction];
[self provideContent:transaction.payment.productIdentifier];
[self finishTransaction:transaction wasSuccessful:YES];
// called when a transaction has been restored and and successfully completed
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
[self recordTransaction:transaction.originalTransaction];
[self provideContent:transaction.originalTransaction.payment.productIdentifier];
[self finishTransaction:transaction wasSuccessful:YES];
// called when a transaction has failed
- (void)failedTransaction:(SKPaymentTransaction *)transaction
if (transaction.error.code != SKErrorPaymentCancelled)
[self finishTransaction:transaction wasSuccessful:NO];
// this is fine, the user just cancelled, so don’t notify
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
#pragma mark -
#pragma mark SKPaymentTransactionObserver methods
// called when the transaction status is updated
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
for (SKPaymentTransaction *transaction in transactions)
switch (transaction.transactionState)
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
要测试上面的新代码,你还需要编写调用 loadStore, canMakePurchases 以及 purchaseProUpgrade 方法的代码。
有关上述代码的详细解释,请参考官方 In App Purchase Programming Guide (IAP编程指南)
上述代码有几个部分是针对我的程序的。例如,在 provideContent:中,NSUserDefaults 中的@”isProUpgradePurchased” BOOL 字段被设定为 YES。程序的其他部分将检查此BOOL值以确定是否需要启动专业版功能。如果你正好也要实现免费升级专业版的功能,那麽你可以使用同样的方法。
2. 添加测试用户
为测试上述代码,你需要在 iTunes Connect 中创建测试用户以对IAP功能进行测试。你可以使用测试帐号购买产品而不被Apple收取费用。
按以下步骤创建测试用户:
登录到 /iphone
进入 iTunes Connect
选择iTunes Connect首页中的 “Manage Users”
选择 “In App Purchase Test User”
选择 “Add New User”
填入用户信息. 所有信息都不必是合法的。建议使用虚假简短的email地址及简短的密码。
选择 “Save”
测试时你需要输入这些email地址和密码。
3. 在你的设备中退出登录
在进行程序购买功能测试前,你必须在你的设备中退出iTunes Store。遵循以下步骤:
打开Settings App
点击 “Store” 行
点击 “Sign Out”
4. 购买测试
现在,终于可以开始进行IAP功能的测试了。测试很简单:
运行你设备中的程序
当程序提示输入用户名和密码时,输入参数用户的信息
如果你使用同一账户进行购买时,系统将提示你已经购买了此产品。按“Yes”就可以再次下载此产品。
实现IAP功能比想象的要複杂许多。我可是经过无数痛苦的经历才完成我的程序。希望能够帮助其他开发者减轻他们的痛苦。应用程序內购买
文章评论 以下网友留言只代表其个人观点,不代表本网站的观点和立场。Once广播对话徐小平,教你如何成为千万富翁_mixdown
主播/制作:艾河(we chat:Actorkyle)本期嘉宾:徐小平
重要通知:Once广播在日前,会陆续将未来所有的节目,发布在官方公众号内;公众号内,可以进行节目收听,留言,评论,打赏,所以,马上在微信公众号内搜索:Onceradio,就可以了解Once的最新动态;同时,Once广播入驻了苹果Podcast,在Podcast软件内搜索并关注Once广播电台,就可以说听到数字形式广播了。
大家还在听Once最新版|苹果OnceiPad版/ iPhone版免费下载
当前位置:
软件截图Once下载信息Once简介
ONCE Fútbol Ecuador es una excelente aplicación para que no te pierdas un solo partido de tu equipo favorito. Podrás disfrutar minuto a minuto los acontecimientos en vivo y mucho más! Campeonatos:- Campeonato Ecuatoriano Serie A y Serie B- Eliminatorias y Mundial FIFA- Copa América- Copa Libertadores- Copa Sudamericana- UEFA Champions League- Liga BBVA de Espa?aDisfruta de:- Resultados minuto a minuto - Notificaciones en vivo de inicio / fin del partido, goles, tarjetas y cambios- Alineaciones - Tablas de posiciones- Calendario - Resultados- Noticias diariasEscoge tus equipos favoritos para recibir notificaciones durante los partidos en vivo. Ademas, comparte el minuto a minuto por Facebook, Twitter o email.更新日志
Corregidos errores menores en notificaciones
PP苹果助手:love25ppcomswift notes-带你走进dispatch_once的世界
招聘信息:
本文投稿文章,作者:秋明txt()最近用苹果官方的API做了一个Swift版的二维码生成和扫描的demo。在要设置AVCaptureMetadataOutput的时候,遇到了一些坑。private&lazy&var&output:&AVCaptureMetadataOutput&=&{
&&&&&&&&let&out&=&AVCaptureMetadataOutput()
&&&&&&&&//&1.获取屏幕的frame
&&&&&&&&let&viewRect&=&self.view.frame
&&&&&&&&//&2.获取扫描容器的frame
&&&&&&&&let&containerRect&=&self.customContainerView.frame
&&&&&&&&let&x&=&containerRect.origin.y&/&viewRect.height
&&&&&&&&let&y&=&containerRect.origin.x&/&viewRect.width
&&&&&&&&let&width&=&containerRect.height&/&viewRect.height
&&&&&&&&let&height&=&containerRect.width&/&viewRect.width
&&&&&&&&out.rectOfInterest&=&CGRect(x:&x,&y:&y,&width:&width,&height:&height)
&&&&&&&&return&out
&&&&}()rectOfInterest的rect设置是以横屏为参考坐标系的,因此需要转化坐标完成转化之后,扫描区域依然不对经过多方填坑,找到了最终问题所在:我的扫码界面采用了storyboard布局,而storyboard上控件的真实frame只有在viewDidLayoutSubviews()函数被调用之后才能获取,而viewDidLayoutSubviews()在视图控制器的生命周期中会被多次调用,而我只想配置一次,重复配置也不科学,因此想通过dispatch_once()来控制配置次数。上面那些自然都是题外话了,swift版二维码生成和扫描的demo会在下次分享给大家。下面通过阅读苹果官方文档,一起走进dispatch_once的世界。1. 初识dispatch_once_t与dispatch_once( )1.1 dispatch_once_t在苹果官方文档中,是这么定义dispatch_once_t的:&/*!
&*&@typedef&dispatch_once_t
&*&@abstract
&*&A&predicate&for&use&with&dispatch_once().&It&must&be&initialized&to&zero.
&*&Note:&static&and&global&variables&default&to&zero.
public&typealias&dispatch_once_t&=&Int从上面我们可以得到以下3个信息:dispatch_once_t是Int的一个别名dispatch_once_t 用来当做dispatch_once()的断言(predicate)来用的dispatch_once_t必须初始化为0同时末尾还有一个提示:static和global variables的默认值为0。这个提示该怎么理解呢?在我们声明一个变量为可选值的时候,若没有为其赋值,其默认值为nil,比如:var&aString:&String?
print(aString)打印的结果为nil于是我就声明了一个全局(global)的dispatch_once_t,然后打印它:var&aToken:&dispatch_once_t
print(aToken)结果不好的事情发生了,系统给报了一个错误:error:&variable&'aToken'&used&before&being&initializedaToken在使用之前必须初始化,说好的默认为0呢?难道是说默认设为0?1.2 dispatch_once( )dispatch_once( )在苹果官方文档中是这样描述的:/*!
&*&@function&dispatch_once
&*&@abstract
&*&Execute&a&block&once&and&only&once.
&*&@param&predicate
&*&A&pointer&to&a&dispatch_once_t&that&is&used&to&test&whether&the&block&has
&*&completed&or&not.
&*&@param&block
&*&The&block&to&execute&once.
&*&@discussion
&*&Always&call&dispatch_once()&before&using&or&testing&any&variables&that&are
&*&initialized&by&the&block.
@available(iOS&4.0,&*)
public&func&dispatch_once(predicate:&UnsafeMutablePointer,&_&block:&dispatch_block_t)从上面我们可以看出: dispatch_once()的作用:执行一段代码块,并且只执行一次。dispatch_once()有两个参数:参数1:predicate,一个指向dispatch_once_t的指针,用来测试block是否执行完成参数2:block,要执行的代码块1.3 dispatch_once()工作原理重点来了,系统是怎么根据predicate指针来判断block是否执行完成的呢?首先,predicate指针所指向的变量的类型为dispatch_once_t,而dispatch_once_t变量初始化时必须设置为0dispatch_once()在进行predicate(断言)判定时,dispatch_once_t变量的值只有为0时,才会执行block,因此初次调用时,block会被调用一次当block执行完毕后,系统会将dispatch_once_t变量的值置为-1,因此再次调用dispatch_once()的时候,就会跳过blockTips:dispatch_once_t是一个只能为0或-1的Int值,默认为0,执行完block,被置为-1。若置为其他值,会报错EXC_BAD_ACCESS。2. dispatch_once实践2.1 global测试//&global测试
var&globalToken:&dispatch_once_t&=&0
func&calledOnce()&{
&print(globalToken)
&&&&dispatch_once(&globalToken)&{
&&&&&&&&print("Called&once&in&global&scope.")
calledOnce()
calledOnce()
calledOnce()globalToken的类型必须设置为变量,因为系统在调用完block之后,会对其进行修改,设为let编译器会报如下错误:error:&cannot&pass&immutable&value&as&inout&argument:&'globalToken'&is&a&'let'执行结果为:0
Called&once&in&global&scope.
-1我们可以看到,block只执行了一次,globalToken的值也被系统修改为-1。2.2 static测试//&static测试
class&MyClass&{
&&&&private&static&var&staticToken:&dispatch_once_t&=&0
&&&&class&func&doItOnce()&{
&&&&&&&&print(staticToken)
&&&&&&&&dispatch_once(&staticToken)&{
&&&&&&&&&&&&print("Called&in&static&scope")
class&MyClassSub:&MyClass&{
&&&&override&static&func&doItOnce(){
&&&&&&&&super.doItOnce()
&&&&&&&&print("called&in&sub&class")
MyClass.doItOnce()
MyClass.doItOnce()
MyClassSub.doItOnce()
MyClassSub.doItOnce()执行结果如下:0
Called&in&static&scope
//&下面为子类调用结果
called&in&sub&class
called&in&sub&class从执行结果我们可以看出,无论是父类调用,还是子类调用,block只执行一次Tips:声明类的类型方法有两个关键字可供选择:static和class;使用class关键字声明,子类可以重写父类方法,而使用static关键字声明,子类则不能重写父类方法,否则会报如下错误:error: class method overrides a 'final' class method2.3 实例测试//&实例测试
class&InstanceTest&{
&&&&private&var&instanceToken:&dispatch_once_t&=&0
&&&&func&doItOncePerInstance()&{
&&&&&&&&dispatch_once(&instanceToken)&{
&&&&&&&&&&&&print("Called&once&per&instance")
let&instance1&=&InstanceTest()
instance1.doItOncePerInstance()
instance1.doItOncePerInstance()
let&instance2&=&InstanceTest()
instance2.doItOncePerInstance()
instance2.doItOncePerInstance()执行结果如下://&instance1调用
Called&once&per&instance
//&instance2调用
Called&once&per&instance2.4 local测试class&LocalTest&{
&&&&func&doItOnce()&{
&&&&&&&&var&localToken:&dispatch_once_t&=&0
&&&&&&&&dispatch_once(&localToken)&{
&&&&&&&&&&&&print("Called&every&time")
let&localTest&=&LocalTest()
localTest.doItOnce()
localTest.doItOnce()测试结果为:Called&every&time
Called&every&time函数每次调用,block都会执行。原因在于localToken为局部变量,每次调用函数时,都会将其初始化为0 。3.小结在苹果的官方文档中,dispach_once_t的是这么描述的:Variables of this type must have global or static scope. The result of using this type with automatic or dynamic allocation is undefined.dispatch_once_t类型的变量必须声明为全局变量或者static 类型的变量,只有如此,block才会执行且只执行一次。在Objcet-C中,我们经常通过使用static声明dispatch_once_t变量来创建单例,也是基于此。通过上面的global测试和static测试,我们也验证了这一点。使用动态分配的方法创建dispatch_once_t类型的变量,结果是不确定的。在实例测试中,我们可以看到,每个实例各执行了一次,但在单个实例的生命周期中,只会执行一次。有时候,我们必须在一些会被多次调用的函数中做一些配置,而实际需求是配置一次即可。然后呢?你懂的。至于将dispatch_once_t声明为局部变量,其实只能说然并卵,没什么实际用处。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量6222点击量5902点击量5827点击量4769点击量4329点击量4199点击量4107点击量4025点击量3958
&2016 Chukong Technologies,Inc.
京公网安备89}

我要回帖

更多关于 苹果4s拍照效果 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信