美文网首页iOS学习
《iOS开发进阶》杂记

《iOS开发进阶》杂记

作者: 永断阎罗 | 来源:发表于2017-08-09 11:10 被阅读0次

    Charles 模拟网络状态

    • 在Charles的菜单上,选择“Proxy” --> “Throttle Setting”项,在弹出的对话框中勾上”Enable Throttling“,并且设置Throttle Preset选项,选择你要模拟的网络状况。

    Core Foundation

    • 在ARC下的内存管理,CFRetain(CF对象),用CFRetain(引用计数器+1)和CFRelease(引用计数器-1)手动管理引用计数器。

    • 当把Core Foundation对象转换成OC的对象是,需要使用bridge相关的关键字告诉编译器如何调整引用计数器。

        __bridge:只做类型转换,不修改相关对象的引用计数,原来的Core Foundation对象在不用时,需要调用CFRelease方法。
        __bridge_retained:类型转换后,不修改相关对象的引用计数,原来的Core Foundation对象在不用时,需要调用CFRelease方法。
        __bridge_transfer:类型转换后,将该对象的引用计数交给ARC管理,Core Foundation在不用时,不再需要调用CFRelease方法。
      

    收起键盘的方法


    • 调用UITextField或UITextView的resignFirstResponder方法
    • 重载UIViewController的touchesBegin方法,再调用[self.view endEditing:YES]; 这样单机UIViewController的任意位置,都能收起键盘。
    • 直接执行[[UIApplication shareApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil]; 用于在获得当前UIViewController比较困难的时候。
    • 直接执行[[[UIApplicatoin shareApplication]keyWindow]endEditing:YES];

    设置App应用内系统控制语言


    • 例如menu控件显示的语言并不是和你当前手机的系统语言一致的,而是根据应用内部的语言设置来显示的。如果没设置就会出现中文应用,显示的是英语控件文字。
      //点击Info.plist ----> 右键选择Open As ----> Source Code -----> 添加如下代码:

      <key>CFBundleLocalizations</key>
        <array>
            <string>zh_CN</string>
            <string>en</string>
      </array>
      

    WindowLevel

    • UIWindow的层级,三个层级。
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;

    GCD让两个线程并行执行

    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group,dispatch_get_global_queue(0,0),^{
        //并行执行的线程一
    });
    dispatch_group_async(group,dispatch_get_global_queue(0,0),^{
        //并行执行的线程二
    });
    dispatch_group_notify(group,dispatch_get_global_queue(0,0),^{
        //汇总结果
    });
    

    JavaScript文件设置调整


    • JavaScript的js后缀的文件默认被拖动到工程中后,实在编译列表中,而不是资源列表中,你手动地调整其位置,否则它就不能打包到IPA文件中。这是一个bug,js文件并不需要编译 ,做混合开发时注意把js文件从Complie Sources 拖到Copy Bundle Resources中。

    清除DeriverdData


    • 当多次重构的工程代码没有错却编译失败时,可以尝试删除DeriverdData目录。(DeriverdData是编译缓存,路径是:~/Library/Developer/Xcode/DerivedData),清除后需重启Xcode。

    模拟器快捷键


    • Command + 1/2/3 :可以切换模拟器的显示比例
    • Option + Shift + 拖动 :可以在模拟器中调出双指拖动效果
    • Option :可以在模拟器中调出双指放大缩小效果
    • Command + Shift + H :是模拟器的home键
    • Command + left/Right :可以切换横竖屏

    修改block之外的变量

    __block int a = 0; //__block的表示:把a的值引用到block中,可修改,非block修饰的变量表示:复制变量的值到block中,只读属性。
    void (^foo) (void) = ^ {
        a = 1;
    }
    

    管理代码片段


    • 把需要快捷输出的代码片段拖到右边“{}”此项中,然后用<#被替换的内容#>的格式,让用户替换掉。
    • 可以把代码片段托管到GitHub上,这样在第三台机器上工作时,就能快速还原。代码片段存放在:~/Library/Developer/Xcode/UserData/CodeSnippets中。

    内购开发流程

    • 后台配置

      • 用 App ID 创建一个新的应用。
      • 在该应用中,创建应用内付费项目,选择付费类型,通常可选的是可重复消费(Consumable)和永久性有效的(Non-Consumable)两种,然后设置好价格、Product ID、购买介绍和截图。(注:Product ID后面开发要用到)。
      • 添加一个用于在sandbox付费的测试用户。(注:苹果对该测试用户的密码要求和正式测试一样,至少要8位,并且同时包含数字和大小写字母)
      • 填写相关的税务、银行和联系人信息。
    • iOS端开发

      • 在工程中引入storekit.framework和#import(StoreKit/StoreKit.h)

      • 获得所有的付费Product ID列表。这个可以用常量存储在本地,也可以由自己的服务器返回。

      • 制作一个界面,展示所有的应用内付费项目。这些应用内付费项目的价格和介绍信息推荐是自己的服务器返回(当然也可以是向App Store查询,不过需要2~3秒钟)

      • 当用户点击一个IAP项目,需要先查询用户是否允许应用内付费。允许才能进行下面步骤。

          if([SKPaymentQueue canMakePayments]) {
              //执行下面第五步
              [self getProductInfo];
          } else {
              NSLog(@"用户禁止应用内付费");
          }
        
      • 先通过IAP的Product ID向App Store查询,获取SKPayment实例,然后SKPaymentQueue的addPayment方法发起一个购买的操作,代码如下所示:

          //下面的ProductId是事先在iTunesConnet中添加好的,已存在的付费项目,否则会查询失败。
          - (void) getProductInfo {
              NSSet *set = [NSSet setWithArray:@[@"ProductId"]];
              SKProductRequest *request = [[SKProductRequest alloc]initWithProductIdentifiers:set];
              request.delegate = self;
              [request start];
          }
          //以上查询的回调函数
          - (void)productsRequest:(SKProductRequest *)request didReceiveResponse:(SKProductResponse *)response {
              NSArray *myProduct = response.products;
              if (myProduct.count == 0) {
                  NSLog(@"无法获取产品的信息,购买失败");
                  return;
              }
              SKPayment *payment = [SKPayment paymentWithProduct: myProduct[0]];
              [[SkPaymentQueue defaultQueue] addPayment:payment];
          } 
        
      • 在ViewDidLoad方法中,将购买页面设置成购买的Observe,代码如下所示:

          - (void) viewDidLoad {
              [super viewDidLoad];
              //监听购买结果
              [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
          }
          - (void) viewDidUnLoad {
              [super viewDidUnLoad];
              [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
          }
        
      • 当用户购买的操作有结果时,就会触发下面的回调函数,相应进行处理即可:

          - (void) patmentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
              switch (transactions.transactionState) {
                  case SKPaymentTransactionStatePurchased: //交易完成
                        [self completeTransaction:transaction];
                        break;
                  case SKPaymentTransactionStateFailed: //交易失败
                        [self failedTransaction:transaction];
                         break;
                  case SKPaymentTransactionStateRestored: //交易重复
                        [self restoreTransaction:transaction];
                         break;
                  case SKPaymentTransactionStatePurchasing: //商品添加列表
                  default:
                          break;
              }
          }
          
          - (void) completeTransaction:(SKPaymentTransaction *)transaction {
              NSString *productIdentifier = transaction.payment.productIdentifier;
              NSString *receipt = [transaction.transcationReceipt base64EncodedString];
              if([ProductIdentifier length] > 0) {
                  //向自己的服务器验证购买凭证
              }
              //在购买队列中移除此商品
              [[SKPaymentQueue defaultQueue] finisTransaction:transaction];
          }
          
          - (void) failedTransaction:(SKPaymentsaction *)transaction {
              if(transaction.error.code != SKErrorPaymentCancelled) {
                  NSLog(@"购买失败");
              }else {
                  NSLog(@"用户取消交易");
              }
              [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
          }
          
          - (void) restoreTransaction:(SKPaymentTransaction *)transaction {
              //对于已购买商品,处理恢复购买的逻辑
              [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
          }
        
      • 服务器验证凭证(可选项)。如果购买成功,需要将凭证发送到服务器上进行验证。考虑到网络异常的情况,iOS端的开发凭证操作应该可以持久化,如果程序退出、崩溃或网络异常,可以恢复重试。

    • 服务端开发

      • 接收iOS端发过来的购买凭证;
      • 判断凭证是否已经存在,是否验证码,然后存储该凭证;
      • 将该凭证发送到苹果的服务器验证,并将验证结果返回给客户端;
      • 如果需要,修改用户相应的会员权限。
    • 注意事项

    相关文章

      网友评论

        本文标题:《iOS开发进阶》杂记

        本文链接:https://www.haomeiwen.com/subject/orttrxtx.html