iOS应用内支付(内购)的个人开发过程及坑!

2023-11-15

本文会给大家详细介绍iOS内购,这是本人16年5月底的开发过程,希望对看完此篇文章的人有所帮助。 
本文基于XcodeVersion 7.3 (7D175)版本,手机是iPhone 6,9.3系统。 
部分地方直接摘自网络,基本上是我的逻辑,省时省心省力。

一. 创建测试App

首先你需要登录 App的ItunesConnection,你会看到如下界面 
这里写图片描述

简单的介绍一下这几个选项 
1.我的App主要用于管理自己的App应用,例如编辑资料,上架,下架等。 
2.销售和趋势主要是来查看App在各个平台的下载量,收入等方面数据,里面有曲线图等图文结合的方式给我们参考。 
3.付款和财务报告显示的是你的收入以及付款等相关信息。 
4.iAd主要是跟广告有关,开发者可以登录到Workbench,通过iAd对应用的广告进行控制。 
5.用户和职能用于生成相应账号,例如苹果沙河测试账号。 
6.协议,税务和银行业务则是你银行相关账户的信息设置。 
在这里我们选择第一个选项,我的App, 然后点击左上角的加号,新建一个用来测试用的App。 
这里写图片描述

点新建 App,会出现新建窗口; 
这里写图片描述

在这里有几个需要填写的地方,名称自己取,平台IOS,语言选择了简体中文,套装ID也就是你的Bundle Identifier,需要你在Certificates页面 申请BundleID,SKU可以理解为用户看一看到的唯一标示,会体现在你的app的App Store的链接中。

二.添加内购

App创建好之后,我们打开创建的App,在左上角选择功能,会看到左侧的App 内购买项目。我们点击右下角的加号,为App添加内购项目。 
这里写图片描述

之后我们会看到类型的选项,如下图

这里写图片描述

官方的注释写的很清楚了,只在这里简单的说下前两种: 
- 消耗型项目 就像你玩游戏需要买金币,买钻石等,只要花钱就可以无限次的购买 
- 非消耗型项目 就像你在App Store购买App,买了一次之后就不用再买第二次,你拥有永久使用权。 
在我们的app中,是充值会员,所以选择的是第一种,可以无限次购买。

这里写图片描述

这里有几个选项,需要填写商品名称,产品ID以及价格等级,简单说明一下 
1. 商品名称根据你的消费道具的实际意义来说明,比如“100颗宝石”,“100金币”等。 
2. 产品ID是比较重要的,由项目自定义,只要唯一即可,因为测试,我在这里随便填写的123,在实际应用中,一定要认真填写。 
3. 价格等级的话“查看价格表”中有对应的说明,可以对照着表中每个国家的货币价格与等级来选择 
接下来是语言选择,和上传快照如下图

这里写图片描述

点击添加语言,填写名称和描述,这里我们依然选择简体中文,如下

这里写图片描述

审核备注,根据实际情况填写,可以不填。而下面的屏幕快照,则是商品图片,以像素为单位,最低尺寸为321,390,尺寸需求如下图,上传即可。

这里写图片描述

到这里为止, 我们的内购项目则添加完成。接下来则是测试阶段了。

三.申请沙盒测试账号(用来测试购买项目)

这个账号,是利用苹果的沙盒测试环境来模拟AppStore的购买流程,你肯定不会想要用真实RMB去购买测试吧? 
首先我们回到iTunes Connect中,在这里我们选择用户和职能。

这里写图片描述

然后在上面的第三个选项沙箱技术测试员中点击加号,添加测试员。

这里写图片描述

在信息填写页面只简单说两句。 
所有信息都可以随意填写,不用管是否真实。 
App Store地区选择,一定要选对,它对应的是你创建的App的地区, 你App是中国的话, 在这里我们依然选择中国。 
此账号只能用来测试,不要在正式的appstore上使用 
填写完毕,点击保存后,我们则生成一个测试账号,当然这个账号是可以随时删除和添加的。

这里写图片描述

之后终于到了写代码的时候了,点开你的Xcode创建你的项目! 
大部分代码都可以在.m文件中实现。

#import "ViewController.h"
#import <StoreKit/StoreKit.h>
#import "SVProgressHUD.h"

@interface ViewController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
@property (nonatomic,copy) NSString *currentProId;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(100, 100, 100, 100);
    button.backgroundColor = [UIColor greenColor];
    [button setTitle:@"6元" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
    [self.view addSubview:button];
}


- (void)btnClick:(UIButton *)button
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    _currentProId = @"123";
    if([SKPaymentQueue canMakePayments]){
        [self requestProductData:product];
    }else{
        NSLog(@"不允许程序内付费");
    }
}

//去苹果服务器请求商品
- (void)requestProductData:(NSString *)type{
    NSLog(@"-------------请求对应的产品信息----------------");

    [SVProgressHUD showWithStatus:nil maskType:SVProgressHUDMaskTypeBlack];

    NSArray *product = [[NSArray alloc] initWithObjects:type,nil];

    NSSet *nsset = [NSSet setWithArray:product];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    request.delegate = self;
    [request start];

}

//收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{

    NSLog(@"--------------收到产品反馈消息---------------------");
    NSArray *product = response.products;
    if([product count] == 0){
        [SVProgressHUD dismiss];
        NSLog(@"--------------没有商品------------------");
        return;
    }

    NSLog(@"productID:%@", response.invalidProductIdentifiers);
    NSLog(@"产品付费数量:%lu",(unsigned long)[product count]);

    SKProduct *p = nil;
    for (SKProduct *pro in product) {
        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);

        if([pro.productIdentifier isEqualToString:_currentProId]){
            p = pro;
        }
    }

    SKPayment *payment = [SKPayment paymentWithProduct:p];

    NSLog(@"发送购买请求");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    [SVProgressHUD showErrorWithStatus:@"支付失败"];
    NSLog(@"------------------错误-----------------:%@", error);
}

- (void)requestDidFinish:(SKRequest *)request{
    [SVProgressHUD dismiss];
    NSLog(@"------------反馈信息结束-----------------");
}
//沙盒测试环境验证
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式环境验证
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
/**
 *  验证购买,避免越狱软件模拟苹果请求达到非法购买问题
 *
 */
-(void)verifyPurchaseWithPaymentTransaction{
    //从沙盒中获取交易凭证并且拼接成请求体数据
    NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];

    NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//转化为base64字符串

    NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接请求数据
    NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];


    //创建请求到苹果官方进行购买验证
    NSURL *url=[NSURL URLWithString:SANDBOX];
    NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
    requestM.HTTPBody=bodyData;
    requestM.HTTPMethod=@"POST";
    //创建连接并发送同步请求
    NSError *error=nil;
    NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
    if (error) {
        NSLog(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
        return;
    }
    NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@",dic);
    if([dic[@"status"] intValue]==0){
        NSLog(@"购买成功!");
        NSDictionary *dicReceipt= dic[@"receipt"];
        NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
        NSString *productIdentifier= dicInApp[@"product_id"];//读取产品标识
        //如果是消耗品则记录购买数量,非消耗品则记录是否购买过
        NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
        if ([productIdentifier isEqualToString:@"123"]) {
            int purchasedCount=[defaults integerForKey:productIdentifier];//已购买数量
            [[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
        }else{
            [defaults setBool:YES forKey:productIdentifier];
        }
        //在此处对购买记录进行存储,可以存储到开发商的服务器端
    }else{
        NSLog(@"购买失败,未通过验证!");
    }
}
//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
    for(SKPaymentTransaction *tran in transaction){
        switch (tran.transactionState) {
            case SKPaymentTransactionStatePurchased:{
                NSLog(@"交易完成");
                // 发送到苹果服务器验证凭证
                [self verifyPurchaseWithPaymentTransaction];
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];

            }
                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加进列表");

                break;
            case SKPaymentTransactionStateRestored:{
                NSLog(@"已经购买过商品");

                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
            }
                break;
            case SKPaymentTransactionStateFailed:{
                NSLog(@"交易失败");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                [SVProgressHUD showErrorWithStatus:@"购买失败"];
            }
                break;
            default:
                break;
        }
    }
}

//交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"交易结束");

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}


- (void)dealloc{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
 
 
  • 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
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195

在这里需要注意几点, 
1. 代码中的_currentProId所填写的是你的购买项目的的ID,这个和第二步创建的内购的productID要一致;本例中是 123。 
2. 在监听购买结果后,一定要调用[[SKPaymentQueue defaultQueue] finishTransaction:tran];来允许你从支付队列中移除交易。 
3. 沙盒环境测试appStore内购流程的时候,请使用没越狱的设备。 
4. 请务必使用真机来测试,一切以真机为准。 
5. 项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。 
6. 真机测试的时候,一定要退出原来的账号,才能用沙盒测试账号 
7. 二次验证,请注意区分宏, 测试用沙盒验证,App Store审核的时候也使用的是沙盒购买,所以验证购买凭证的时候需要判断返回Status Code决定是否去沙盒进行二次验证,为了线上用户的使用,验证的顺序肯定是先验证正式环境,此时若返回值为21007,就需要去沙盒二次验证,因为此购买的是在沙盒进行的。

附:苹果支付错误目录

Status Code Description
21000 The App Store could not read the JSON object you provided.
21002 The data in the receipt-data property was malformed or missing.
21003 The receipt could not be authenticated.
21004 The shared secret you provided does not match the shared secret on file for your account.Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
21005 The receipt server is not currently available.
21006 This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
21007 This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
21008 This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.

参考: 
1.  iOS开发之内购-AppStore
2. 苹果官方文档

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS应用内支付(内购)的个人开发过程及坑! 的相关文章

  • 在flutter中跟踪背景位置时使用background_locator插件时出现问题

    我正在尝试使用 flutter 跟踪后台位置 为此我正在使用背景定位器 https pub dev packages background locator插入 它的实现方式是注册某些静态回调函数 我声明了一个 File 类型的类变量来在后台
  • iPhone - 创建图像网格列表

    我正在开发一个应用程序 它从网站获取图像并使用网格视图向用户显示 例如Apple的照片应用程序 当您点击图像时 我会推送一个显示图像信息和其他内容的视图控制器 实现这个的更好方法是什么 我想到了自定义 UITableViewCell 我见过
  • 应用程序在第二次运行 nsnull 计数的循环时崩溃

    我有一个循环 第一次运行正常 但第二次循环时我得到 NSNull count unrecognized selector sent to instance 0x3a094a70 Terminating app due to uncaught
  • 检测您何时进入/退出 Xamarin.iOS 中的主线程

    Xamarin MonoTouch 有没有办法检测主线程中是否正在调用代码 我正在寻找类似于Java的东西EventQueue isEventDispatchThread 我发现 Swing 编程很方便assert时不时 或有时assert
  • 如何更改 UISwitch 关闭状态的默认颜色?

    我想更改 UISwitch 中 onTintColor 的颜色以表示关闭状态 切换位于表格视图中 并且以编程方式进行切换 settingsSwitch setBackgroundColor UIColor whiteColor settin
  • 自动调整大小完成后如何获取帧大小

    我想知道 如何以及何时 viewDidLoad viewWillAppear viewDidAppear 可以获得自动调整大小以适合其父视图的 UIViews 框架大小 从你的问题中不清楚你为什么想要它 但我想这是为了布局你的子视图 幸运的
  • iOS App布局错误,调用状态栏

    在主动通话和应用程序布局期间面临状态栏问题 我正在使用自动布局 当我运行应用程序 然后开始通话时 一切正常 UI 会随着状态栏的更改而正确缩放 但是 如果我首先开始通话 然后运行应用程序 应用程序屏幕会移动到底部 20pt 就像它们对新状态
  • 使用 UIImagePickerController 的应用程序在拍照后选择“使用照片”时冻结

    我现在正在开发一个简单的照片和视频捕获应用程序 该应用程序成功地允许用户按下按钮即可拍摄照片或视频 但是 一旦您完成拍摄照片或视频 它就会提供 2 个选项 重新拍摄 和 使用照片 或 使用视频 具体取决于您使用的选项 如果用户点击 重新拍摄
  • 对 UIImage 进行方形裁剪,导致图像拉伸

    当尝试执行 UIImage 的中心裁剪时 我得到以下结果 左侧是原始图像640 1136 右边是适合正方形的裁剪图像UIImageView at 320 320 turns to 我对比率元素进行了相当多的修改 以便它可以正确检测要修剪的量
  • WebGL iOS 渲染为浮点纹理

    我正在尝试在 iOS Safari 上的 WebGL 中渲染浮点纹理 而不是在本机应用程序中 我已经设法让 iOS 读取手动 例如从 JavaScript 创建的浮点纹理 但是当我创建浮点类型的帧缓冲区并使用 GPU 渲染到其中时 它不起作
  • iOS 内存警告

    我正在尝试使用从 Parse 数据库下载的图像填充集合视图 但我收到内存警告 然后偶尔崩溃 有谁知道其他应用程序如何设法呈现这么多图像而不崩溃 有人可以告诉我如何优化我已有的东西吗 这是所有相关代码 https gist github co
  • 切换到工作区并在 Xcode 中添加 CocoaPods 后提交 git 吗?

    我刚刚在 Xcode 5 中将 CocoaPods 添加到我当前的项目中 当然 CocoaPods 创建了一个工作区 并且我已在 Xcode 中启动了该工作区 我在工作区中看到了我的项目和 Pods 项目 我的项目从第一天起就处于源代码控制
  • 从 Core Data、iOS 获取最后插入的项目

    有没有办法获取核心数据数据库中最后插入的项目 这将返回最后插入的对象 setFetchLimit 1 和 setFetchOffset 所有条目数 1
  • 在 Swift 中检查一个数组是否包含另一个数组的所有元素

    我想为数组编写一个扩展来检查一个数组是否包含另一个数组的所有元素 在我的用例中它是字符串对象 但我一直得到 Cannot convert value of type T Generator Element to expected argum
  • 如果 NSExtensionActivationRule 设置为仅音频,则共享扩展不会出现在有功能的应用程序中

    我正在尝试创建一个共享扩展 用户可以从任何有能力的应用程序上传她的录音 该文档甚至有一个简单的示例 请参阅声明共享或操作扩展支持的数据类型 https developer apple com library content document
  • 具有多种自定义单元格类型的 RxSwift 表视图

    我想知道是否有任何代码示例RxSwift当我可以在一个表视图中使用多个自定义单元格时 例如 我有两个部分 第一部分有 10 个单元格 类型为CellWithImage标识符和第二部分有 10 个带有类型的单元格CellWithVideo标识
  • Swift 中 UIImages 的淡入淡出动画

    我有一组图像 我希望它们在登录屏幕的背景中淡出 我无法在 swift 中找到任何可以做到这一点的东西 有什么办法我可以做到吗 这是我当前的代码 override func viewDidLoad super viewDidLoad star
  • iOS 对 Google 云消息传递的支持

    我在谷歌的开发者控制台中看到 GCM 允许为 iOS 生成 API 密钥 我在网上搜索了有关如何在 iOS 应用程序中通过 GCM 实现推送通知的任何类型的文档 但没有找到答案 真的有可能在 iOS 应用程序中使用 GCM 实现推送通知 j
  • 下标:使用字符串枚举访问我的字典值

    我想做类似的事情 使用字符串枚举访问我的字典值 我试图重载字典的下标但没有成功 访问字典 let district address JsonKeys district 其中 JsonKeys 是 enum JsonKeys String c
  • 通用类不会将委托调用转发给具体子类

    鉴于以下情况 protocol EntityType var displayString String get extension String EntityType var displayString String return self

随机推荐

  • 合并排序(归并排序)

    合并排序 大致思想便是先将数组中的元素拆分成若干小部分 然后再将这些小部分按照顺序进行重新组合 从而实现排序 很明显 这里用到了分治法的思想 即将一个大问题分成若干个相同的小问题 因为问题规模变小了 所以解决问题的难度也随之减小 试想一下
  • 用户留存的计算

    用户留存的计算 基本是老生常谈了 可是这么多年下来 关于留存的计算 真的是差异太大了 最初版 将每个用户的所有交易月份用group concat 函数进行连接 把对应的结果导出到excel中 然后再用countifs来进行计算 这个方法大概
  • shell脚本中嵌入二进制文件

    最近有人问我 一个集群监控软件的安装文件特别 诡异 说脚本里有 乱码 却能执行 是怎么回事 我看了才发现这个东西原来是典型的脚本嵌套代码的模式 这里就讲讲吧 反正好久没写东西了 某些比较 拽 的单位在发布Linux软件时以一种特殊的形式发布
  • jdbc工作原理

    JDBC是Java数据库连接技术的简称 提供连接各种常用数据库的能力 一 JDBC API 提供者 sun公司 内容 供程序员调用的接口与类 集成在java sql和javax sql包中 如 DriverManager类 Connecti
  • Conditional GAN

    Conditional GAN CGAN 条件GAN 是 Mehdi Mirza 于2014年11月份发表的一篇文章 也是 GAN 系列的早期经典模型之一 是目前许多GAN应用的前身 文章的想法是 希望 可以控制 GAN 生成的图片 而不是
  • 五年软件测试人员,碰到这样的面试题居然心虚...

    我要跳槽 都说金三银四涨薪季 我是着急忙慌的准备简历 5年软件测试经验 可独立测试大型产品项目 熟悉项目测试流程 薪资要求 5年测试经验起码能要个20K吧 我加班肝了一页半简历 投出去一周 面试电话倒是不少 自信满满去面试 现场被问了这么几
  • 腾讯云免费SSL证书申请流程_每年免费50个HTTPS证书

    2023腾讯云免费SSL证书申请流程 一个腾讯云账号可以申请50张免费SSL证书 免费SSL证书为DV证书 仅支持单一域名 申请腾讯云免费SSL证书3分钟即可申请成功 免费SSL证书品牌为TrustAsia亚洲诚信 腾讯云百科分享腾讯云免费
  • [每天一个cmake技巧]cmake开启多核编译

    开启多核编译 可以加快编译速度 大大提升编译效率 具体操作如下 cmake build target all j12 加上 j12即可或者电脑性能足够好 j16
  • 软件(自动化)测试面试基础知识点汇总

    为什么要做接口测试 接口的由来 连接前后端以及移动端 因为不同端的工作进度不一样 所以需要对开始出来的接口进行接口测试 做接口测试的好处 1 节约时间 缩短项目成本 2 提高工作效率 3 提高系统的健壮性 你在项目中如何做接口测试 首先 当
  • 总结——C语言操作符

    总结 C语言操作符 一 算术操作符 算术标识符 加法运算符 加法运算符 加法运算符 加法运算符 加法运算符 只能用于整型 二 移位操作符 移位操作符有两种 gt gt 右移操作符 lt lt 左移操作符 右移操作时分为两种情况 算术右移 逻
  • [leetcode] 827. 最大人工岛

    class Solution private int size 507 507 int fa 507 507 void init for int i 0 i lt n m i fa i i size i 1 int find int x i
  • 华为OD机试真题 完美走位 JavaScript java python c++ 参考解题

    题目描述 在第一人称射击游戏中 玩家通过键盘的A S D W四个按键控制游戏人物分别向左 向后 向右 向前进行移动 从而完成走位 假设玩家每按动一次键盘 游戏人物会向某个方向移动一步 如果玩家在操作一定次数的键盘并且各个方向的步数相同时 此
  • vscode vue : 无法加载文件 C:\Users\xgy\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。有关 详细信息,请参阅 https:

    使用VSCode执行vue V时出现 vue 无法加载文件 C Users xgy AppData Roaming npm vue ps1 因为在此系统上禁止运行脚本 有关 详细信息 请参阅 https go microsoft com f
  • C++11 raw strings literals tutorial

    Now that I have a working system that can compile both regular expressions and raw strings literals it is time to show y
  • 每天Leetcode 刷题 初级算法篇-颠倒二进制位

    题目要求 力扣题解 代码 program test description author Long Ao Tian create 2021 02 27 15 15 public class Solution38 you need treat
  • 9、函数知识点总结(函数概述、参数、闭包、特殊对象,js的预编译,高阶函数)

    目录 9 1 函数概述 9 1 1 函数定义 9 1 2 函数调用 9 1 3 函数提升 9 1 4 自调用函数 9 1 5 函数名后的多个括号 9 2 函数参数 9 3 js的预编译 9 3 1 函数预编译 9 3 2 全局预编译 9 3
  • 在UCGUI中增加汉字显示的说明.

    在UCGUI中增加汉字显示的说明 UCGUI中本身只支持E 没有提供中文的字库的 C源码文件 但是我们可以通过下面的方式来实现汉字的显示 我们知道 在DOS下经常利用点阵来显示汉字 带汉字显示的程序 很多都会自己带上汉字库 这个字库里放的就
  • 解决MySQL:ERROR 1045 (28000): Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO)

  • 程序员必备在线代码对比工具 检查新旧代码差异化

    在工作的时候有用到代码比对工具 用来检查功能调试的时候功能迭代的时候出现故障 希望检查和原始代码到底有什么区别 因此 老蒋本来今天打算整理8 10个在线代码对比工具的 但是考虑到我们在选择工具的时候 在众多工具中选择一款适合自己的即可 否则
  • iOS应用内支付(内购)的个人开发过程及坑!

    本文会给大家详细介绍iOS内购 这是本人16年5月底的开发过程 希望对看完此篇文章的人有所帮助 本文基于XcodeVersion 7 3 7D175 版本 手机是iPhone 6 9 3系统 部分地方直接摘自网络 基本上是我的逻辑 省时省心