2015-08-22 13:09:06 yuxiaohen 阅读数 2694
  • MyBatis 入门视频教程

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层框架。主要学会对数据库的增删改查

    12492 人正在学习 去看看 刘英杰

本文参考如下资料(建议阅读):

a). 公钥加密算法到底什么鬼

b). The ins and outs of code signing an iOS app

c). 代码签名探析


我们先从code signing的作用说起吧


1. 作用

code signing的最终作用就是保证我们在iOS上的应用从开发者机器上build出来后,到最终安装到用户的iOS设备上,不会被篡改。

至于权限控制,也是基于code signing来保证的。


2. 怎么做到的

下文的内容需要我们对公钥加密算法有所了解,这在参考资料a中有述。


1). 如何签名

根据参考资料b中的签名技能,对app中的binary、script以及其他资源一一进行签名(计算每个文件的摘要,然后将摘要使用私钥加密),然后把签名过的文件放到一个CodeResources的plist文件中。(这个文件存放在_CodeSignature文件夹中),我们不妨看一个实例:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <key>files</key>
  6. <dict>
  7. <key>AppIcon29x29@2x.png</key>
  8. <data>
  9. eanTrclP/4jBcw+pZZDeVPimJ7g=
  10. </data>
  11. <key>AppIcon29x29@2x~ipad.png</key>
  12. <data>
  13. eanTrclP/4jBcw+pZZDeVPimJ7g=
  14. </data>
  15. <key>AppIcon40x40@2x.png</key>
  16. <data>
  17. xEo0NvwYxXdtywn3iD8yDaF6V1A=
  18. </data>
  19. <key>AppIcon40x40@2x~ipad.png</key>
  20. <data>
  21. xEo0NvwYxXdtywn3iD8yDaF6V1A=
  22. </data>
  23. <key>AppIcon60x60@2x.png</key>
  24. <data>
  25. rMa2+pGtRq8pN4LRcp+dCn5Kai8=
  26. </data>
  27. <key>Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib</key>
  28. <dict>
  29. <key>hash</key>
  30. <data>
  31. t/7wowkj3how49ccMtcw+bat3sQ=
  32. </data>
  33. <key>optional</key>
  34. <true/>
  35. </dict>

完整的太大了,我们截取一小段观摩。

可以看到key就是文件的名称,data就是文件的签名,由于这个签名无法被篡改,所以plist文件本身不加密也无所谓。


2). 用什么签名

通过前面的参考资料,我们可以了解实际上签名唯一需要的就只是私钥。但在iOS应用签名中,这还不够,我们还需要证书,app id,权限声明,iOS设备,而这些材料我们又可以打包到一种叫做Provision Profile的东西中去,我们在签名的时候(使用mac os x的codesign程式)也只能提供provision profile来工作。

一个Provision Profile的典型结构:

我们来逐一解析各个材料的作用和获取途径(下述内容包含一些臆断的部分,我会用红字标出,因为Apple实在是太封闭了,有些东西我还没没法了解到)。

a). 私钥:实际上私钥和公钥总是成对工作的,缺失其中任何一个之后另一个也是废物一个。在生成证书的时候自然而然会生成密钥对(而且系统会自动关联它们),所以我们放到证书中具体讲述。

b). 证书:为什么需要证书?在前面参考资料中我们了解到,证书实际上是一种身份验证的东西,可想而知这个东西实际上只是iOS系统单方面需要,我们签名实际上并不会用到。证书分为Development/Production(Development/Production对程序的影响本文不予讨论),这在证书中可以看到:

当app安装到iOS上时,iOS系统将取用provision profile中的DeveloperCertificates中的证书来结合CodeResource对app中的文件进行签名验证(证书中的公钥可以解密签名,具体请看参考资料中的『公钥加密算法到底什么鬼』),以确保app中的文件没有被篡改过。

通过参考资料我们了解到生成一个证书文件需要提交一个CSR文件到Apple,然后Apple生成证书给我们,而生成CSR文件的时候就需要我们有密钥对,所以生成证书的时候我们要么会用一个已存在的密钥对,要么就会生成一个新的密钥对。

c). app id:app id用于唯一标识一个应用,一个app在生成的时候会有这个属性,而provision profile中的application-identifier也必须与这个相匹配,值得注意的是匹配并不代表相等,比较贴切的比喻是大于,例如provision profile中的app id如果是*,那将可用于给任何一个app进行签名。但当我们需要用到一些比较特殊的服务的时候就需要provision profile中的app id和app中的app id相等了,比如Apple Push Notification Service。

d). 权限声明:provision profile中的Entitlements和app中的权限声明必须要匹配。

c). iOS设备:ProvisionedDevices包含了使用Development证书或者Ad-hoc证书发行app时可以运行app的设备列表。

2016-02-23 09:22:30 JgPFei 阅读数 325
  • MyBatis 入门视频教程

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层框架。主要学会对数据库的增删改查

    12492 人正在学习 去看看 刘英杰

An error was encountered while running (Domain =FBSOpenApplicationErrorDomain, Code = 4)

 

iOS simulator运行程序出现问题:

An error wasencountered while running (Domain = FBSOpenApplicationErrorDomain, Code = 4)

 

解决方案:

iOS Simulator----> Reset Contents and Settings----> Reset


2016-10-31 16:11:12 kuangdacaikuang 阅读数 4180
  • MyBatis 入门视频教程

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层框架。主要学会对数据库的增删改查

    12492 人正在学习 去看看 刘英杰

iOS 开发 code sign 代码签名深入剖析

前言

这里写图片描述
三个模块:

//代码签名授权
Code Signing Entitlements
//代码签名身份
Code Signing Identity
//描述文件/配置文件
Provisioning Profile

1.点击这里—-苹果官网code sign guide

2.代码签名 (code signing) 和配置文件 (provisioning),是做iOS开发绕不过的坎,报错的时候也是很不容易解决的,终究其原因,就是对苹果为iOS开发设置的一整套安全机制理解不到位导致的,平时大家都集中时间处理开发中遇到的需求问题,在这里投入的时间不够,到时出现错误时,不晓得从哪里下手

3.苹果的很多东西都是闭源的,代码签名就是一个难以理解的神秘黑盒,我们无法直接看到代码签名的运作过程,它们隐藏在 iOS 系统内部和 SDK 之中.想要理解code sign的运作,就不得不了解证书和秘钥了

证书( Certificates)和密匙(Keys)

作为一个 iOS 开发者,在你开发使用的机器上应该已经有一个证书,一个公钥,以及一个私钥。这些是代码签名机制的核心

打开–钥匙串—我的证书
这里写图片描述

  1. 可以看到所有你持有的私钥相对应的证书。
  2. 要用一个证书设置代码签名,必须拥有私钥,所以所有拥有私钥的证书都会被列在这里。
  3. 如果拥有一个证书的私钥,可以展开证书并将它的私钥显示出来:
  4. 如果要导出证书,例如为了备份(强烈建议进行),一定要记得展开证书那一条显示出私钥并将两行都选中。且导出后的证书就是.p12格式的文件,做推送时,就是这样的文件

证书/认证机构/有效期

  1. 一个证书是一个公钥加上许多附加信息,这些附加信息都是被某个认证机构(Certificate Authority 简称 CA)进行签名认证过的,认证这个证书中的信息是准确无误的。
  2. 对于 iOS 开发来说这个认证机构就是苹果的认证部门 Apple Worldwide Developer Relations CA。
  3. 认证的签名有固定的有效期,这就意味着当前系统时间需要被正确设置,因为证书是基于当前时间进行核对。这也是为什么将系统时间设定到过去会对 iOS 造成多方面破坏的原因之一。
  4. 对于iOS开发,有两种证书:开发证书(Develope)和发布证书(Distribution).iOS 系统会利用这个信息来判断你的应用是运行在开发模式下还是发布模式,并据此判断以切换应用运行规则

证书/签名/公钥/私钥

  1. 为了让拥有公钥的证书起作用,我们需要有私钥。
  2. 私钥是你在为组成应用的二进制文件进行签名时派上用场的。没有私钥,你就无法用证书和公钥对任何东西设置签名.
  3. 签名过程本身是由命令行工具 codesign 来完成的。
  4. 如果你在 Xcode 中编译一个应用,这个应用构建完成之后会自动调用 codesign 命令进行签名,codesign 也正是给你提供了许多格式友好并且有用错误信息的那一个工具。你可以在 Xcode 的 project settings 中设置代码签名信息。
    这里写图片描述

注意:

  1. Xcode 只允许在有限的选项中进行选择,这些选项都是既拥有公钥也拥有私钥的证书。
  2. 如果在选项中没有出现你想要的那一个,那么你需要检查的第一件事情就是你是否拥有这个证书的私钥。
  3. 在这里需要区分开用于开发测试还是用于发布,如果想要在机器上测试你的应用,你需要用用于开发测试的那一对密匙来进行签名,如果你是要发布应用,无论是给测试人员还是发布到 APP Store,你需要用用于发布的那一对密匙来进行签名。
  4. Xcode 6之后 的 project settings 中出现了设置配置文件(Provisioning Profile)的选项。如果你选择了某一个配置文件,你必须选择这个配置文件的证书中所包含的公钥所对应的那个密匙对,或者你可以选择让 Xcode 自动完成正确的设置

已签名应用–签名信息的查看和修改

  1. 原理理解:一个已签名的可执行文件的签名包含在 Mach-O 二进制文件格式中;对于例如脚本这样的非 Mach-O 可执行文件,就存放在该文件系统的的扩展属性中。这种做法使得在 OS X 和 iOS 上的任何可执行二进制文件都可以被设置签名:不论是动态库,命令行工具,还是 .app 后缀的程序包。这也意味着设置签名的过程实际上会改动可执行文件的文件内容,将签名数据写入二进制文件中。
  2. 如果你拥有一个证书和它的私钥,那么用 codesign 来设置签名非常简单,我们现在尝试用下面列出的这个证书来为 Example.app 设置签名:
$ codesign -s 'iPhone Developer: 151245000@qq.com (4KPK36MFV)' Example.app
  1. 如果你想为某一个 app 程序包重新设置签名,那么这个工具就很有用了。为了重新设置签名,你必须带上 -f 参数,有了这个参数,codesign 会用你选择的签名替换掉已经存在的那一个:
$ codesign -f -s 'iPhone Developer: 151245000@qq.com (4KPK36MFV)' Example.app

codesign 还可以为你提供有关一个可执行文件签名状态的信息,这些信息在出现不明错误时会提供巨大的帮助。举例来说,$ codesign -vv -d Example.app 会列出一些有关 Example.app 的签名信息

'Executable'=/Users/toto/Library/Developer/Xcode/DerivedData/Example-cfsbhbvmswdivqhekxfykvkpngkg/Build/Products/Debug-iphoneos/Example.app/Example
'Identifier'=ch.kollba.example
'Format'=bundle with Mach-O thin (arm64)
CodeDirectory v=20200 size=26663 flags=0x0(none) hashes=1324+5 location=embedded
Signature size=4336
'Authority'=iPhone Developer: 151245000@qq.com (4KPK36MFV)
'Authority'=Apple Worldwide Developer Relations Certification Authority
'Authority'=Apple Root CA
'Signed Time'=29.09.2014 22:29:07
'Info.plist entries'=33
'TeamIdentifier'=DZM8538E3E
Sealed Resources version=2 rules=4 files=120
Internal requirements count=1 size=184
  1. 以 Authority 开头的那三行。这三行告诉你到底是哪一个证书为这个 app 设置了签名。在这里当然是我的证书,iPhone Developer: 151245000@qq.com (4KPK36MFV)。我的这个证书则是被证书 Apple Worldwide Developer Relations Certification Authority 设置了签名的,依此类推这个证书则是被证书 Apple Root CA 设置了签名。

  2. 在 Format 中也包含了一些关于代码的信息:Example.app 并不单单是一个可执行文件,它是一个程序包,其中包含了一个 arm64 二进制文件。从 Executable 中的路径信息你可以看出,这是一个以测试为目的的打包,所以是一个 Mach-O thin 的二进制文件。

  3. 在一堆诊断信息中还包含了两个非常有趣的条目。 Identifier 是我在 Xcode 中设置的 bundle identifier。 TeamIdentifier 用于标识我的工作组(系统会用这个来判断应用是否是由同一个开发者发布)。此外用于发布应用的证书中也包含这种标识,这种标识在区分同一名称下的不同证书时非常有用。

  4. 下面我们来检查一下封印是否完好:

$ codesign --verify Example.app

授权机制 (Entitlements) 和配置文件 (Provisioning)

原理理解:

即使你可以让应用运行起来,在 iOS 上你的应用能做什么依然是受限制的。这些限制是沙盒管理的。

沙盒和代码签名机制是不同的。代码签名保证了这个应用里所包含的内容正如它所说的那样不多不少,而沙盒则是限制了应用访问系统的资源。

这两种技术是相互合作来发挥作用的,它们都能阻止你的应用运行,也都能在 Xcode 中引起奇怪的问题。但是在日常开发过程中,沙盒可能会更经常引起问题。沙盒机制在什么时候会引起问题呢,大多数情况下都是由于一个叫做授权的机制决定的。

授权机制

授权机制决定了哪些系统资源在什么情况下允许被一个应用使用。简单的说它就是一个沙盒的配置列表,上面列出了哪些行为被允许,哪些会被拒绝。

很可能你已经猜到授权机制也是按照 plist 文件格式来列出的。Xcode 会将这个文件作为 –entitlements 参数的内容传给 codesign ,这个文件内部格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>application-identifier</key>
        <string>7TPNXN7G6K.ch.kollba.example</string>
        <key>aps-environment</key>
        <string>development</string>
        <key>com.apple.developer.team-identifier</key>
        <string>7TPNXN7G6K</string>
        <key>com.apple.developer.ubiquity-container-identifiers</key>
        <array>
                <string>7TPNXN7G6K.ch.kollba.example</string>
        </array>
        <key>com.apple.developer.ubiquity-kvstore-identifier</key>
        <string>7TPNXN7G6K.ch.kollba.example</string>
        <key>com.apple.security.application-groups</key>
        <array>
                <string>group.ch.kollba.example</string>
        </array>
        <key>get-task-allow</key>
        <true/>
</dict>
</plist>

在 Xcode 的 Capabilities 选项卡下选择一些选项之后,Xcode 就会生成这样一段 XML。 Xcode 会自动生成一个 .entitlements 文件,然后在需要的时候往里面添加条目。

当构建整个应用时,这个文件也会提交给 codesign 作为应用所需要拥有哪些授权的参考。这些授权信息必须都在开发者中心的 App ID 中启用,并且包含在配置文件中。在构建应用时需要使用的授权文件可以在 Xcode build setting 中的 code signing entitlements 中设置。

$ codesign -d --entitlements - Example.app 

会列出一个和前面的很像的 XML 格式的属性列表。你可以将这个文件的内容添加进一个脚本,每次构建应用时用脚本检查是否包含了推送服务的授权信息,以此确保推送服务工作正常。在这里推送服务只是一个例子,你使用的服务越多,这样的时候都添加推送通知的授权,以保证可以注册推送通知。Xcode 6 之后,授权信息列表会以 Example.app.xcent 这样的名字的文件形式包含在应用包中。

配置文件

在整个代码签名和沙盒机制中有一个组成部分将签名,授权和沙盒联系了起来,那就是配置文件 (provisioning profiles)。

每一个 iOS 开发者可能都花费过相当的时间研究如何设置配置文件,这个环节也正是会经常出问题的地方。

一个配置文件中存放了系统用于判断你的应用是否允许运行的信息,这就意味着如果你的配置文件有问题,修复起来会相当烦人。

一个配置文件是一组信息的集合,这组信息决定了某一个应用是否能够在某一个特定的设备上运行。配置文件可以用于让应用在你的开发设备上可以被运行和调试,也可以用于内部测试 (ad-hoc) 或者企业级应用的发布。Xcode 会将你在 project setting 中选择的配置文件打包进应用。
这里写图片描述

我们下面来仔细研究一下配置文件。如果你要在自己的机器上找到配置文件,在这个目录下 ~/Library/MobileDevice/Provisioning Profiles。Xcode 将从开发者中心下载的全部配置文件都放在了这里。

这里写图片描述

配置文件并不是一个 plist 文件,它是一个根据密码讯息语法 (Cryptographic Message Syntax) 加密的文件

采用 CMS 格式进行加密使得配置文件可以被设置签名,所以在苹果给你这个文件之后文件就不能被改变了。配置文件的签名和应用的签名不是一回事,它是由苹果直接在开发者中心 (developer portal) 中设置好了的。

某些版本的 OpenSSL 可以读取这种格式,但是 OS X 自带那个版本并不行。幸运的是命令行工具 security 也可以解码这个 CMS 格式,那么我们就用 security 来看看一个 .mobileprovision 文件内部是什么样子:

$ security cms -D -i example.mobileprovision

这个命令会输出签名信息中的内容,接下来你会得到一个 XML 格式的 plist 文件内容输出。

这个列表中的内容是 iOS 用于判断你的应用是否能运行在某个设备上真正需要的配置信息,每一个配置文件都有它自己的 UUID 。Xcode 会用这个 UUID 来作为标识,记录你在 build settings 中选择了哪一个配置文件。

首先来看 DeveloperCertificates 这项,这一项是一个列表,包含了可以为使用这个配置文件的应用签名的所有证书。如果你用了一个不在这个列表中的证书进行签名,无论这个证书是否有效,这个应用都无法运行。所有的证书都是基于 Base64 编码符合 PEM (Privacy Enhanced Mail, RFC 1848) 格式的。要查看一个证书的详细内容,将编码过的文件内容复制粘贴到一个文件中去,像下面这样:

-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIIE/IgVItTuH4wDQYJKoZIhvcNAQEFBQAwgZYxCzA…
-----END CERTIFICATE-----

可能会注意到在 Entitlements 一项中包含了你的应用的所有授权信息,这些授权信息是你在开发者中心下载配置文件时在 App ID 中设置的,理想的情况下,这个文件应该和 Xcode 为应用设置签名时使用的那一个同步,但这种同步并不能得到保证。这个文件的不一致是比较难发现的问题之一。

举例来说,如果你在 Xcode 中添加了 iCloud 键值对存储授权 (com.apple.developer.ubiquity-kvstore-identifier),但是没有更新,重新设置并下载新的配置文件,旧的配置文件规定你的应用并没有这一项授权。那么如果你的应用使用了这个功能,iOS 就会拒绝你的应用运行。这也是当你在开发者中心编辑了应用的授权,对应的配置文件会被标记为无效的原因。

如果你打开的是一个用于开发测试的证书,你会看到一项 ProvisionedDevices,在这一项里包含了所有可以用于测试的设备列表。因为配置文件需要被苹果签名,所以每次你添加了新的设备进去就要重新下载新的配置文件。

总结

  1. 代码签名和配置文件这一套大概是一个 iOS 开发者必须处理的仅次于编码的最复杂的问题之一。

  2. 虽然了解每一个部分是怎么运作的很有帮助,但是要控制好所有这些设置和工具其实是一件很消耗时间的事情,特别是在一个开发团队中,到处发送证书和配置文件显然很不方便。虽然苹果在最近几次发布的 Xcode 中都尝试改善,但是我不是很确定每一项改动都起到了好的作用。处理代码签名是每个开发者必过的大坑。

  3. 虽然处理代码签名对于开发者来说非常繁琐,但不可否认正是它使得 iOS 对于用户来说是一个非常安全的操作系统。所以为代码签名和配置文件进行的这些麻烦设置并不是徒劳无功。

原文: Inside Code Signing

iOS code
2016-12-12 15:37:34 u013954399 阅读数 130
  • MyBatis 入门视频教程

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层框架。主要学会对数据库的增删改查

    12492 人正在学习 去看看 刘英杰

UIButton *informationCardBtn = [UIButton buttonWithType:UIButtonTypeCustom];

        [informationCardBtn addTarget:self action:@selector(enterehzFilesVC:) forControlEvents:UIControlEventTouchUpInside];

        [informationCardBtn setImage:[UIImage imageNamed:@"个人_未点击"] forState:UIControlStateNormal];

        

        [informationCardBtn sizeToFit];

        UIBarButtonItem *informationCardItem = [[UIBarButtonItem alloc] initWithCustomView:informationCardBtn];

        

        

        UIBarButtonItem *fixedSpaceBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];

        fixedSpaceBarButtonItem.width = 22;

        

        

        UIButton *settingBtn = [UIButton buttonWithType:UIButtonTypeCustom];

        [settingBtn addTarget:self action:@selector(enterTeamCard:) forControlEvents:UIControlEventTouchUpInside];

        [settingBtn setImage:[UIImage imageNamed:@"商家_未点击"] forState:UIControlStateNormal];

        [settingBtn sizeToFit];

        UIBarButtonItem *settingBtnItem = [[UIBarButtonItem alloc] initWithCustomView:settingBtn];

        

        self.navigationItem.rightBarButtonItems  = @[informationCardItem,fixedSpaceBarButtonItem,settingBtnItem];



UIButton *detailButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 44)];

        [detailButton setImage:[UIImage imageNamed:@"group_detail"] forState:UIControlStateNormal];

        [detailButton addTarget:self action:@selector(showGroupDetailAction) forControlEvents:UIControlEventTouchUpInside];

        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:detailButton];


UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]initWithTitle:@"退出" style:UIBarButtonItemStylePlain target:self action:@selector(leftBarButtonItemPressed:)];

    [self.navigationItem setLeftBarButtonItem:leftButton];



dispatch_async(dispatch_get_global_queue(0, 0), ^{

        

        dispatch_async(dispatch_get_main_queue(), ^{

            

        });

    });



NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];//str->data

            NSDictionary *rootDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

            NSLog(@"NSJSONSerialization=%@", rootDic);


__weak typeof(self)weakSelf = self;


日期转换为时间戳 (日期转换为秒数)

NSDate *date = [NSDate date];

NSLog(@"当前日期为:%@",date);

NSTimeInterval timeStamp= [date timeIntervalSince1970];

NSLog(@"日期转换为时间戳 %@ = %f", date, timeStamp);


时间戳转日期 (秒数转日期)

NSString *timeStamp2 = @"1414956901";

long long int date1 = (long long int)[timeStamp2 intValue];

NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:date1];

NSLog(@"时间戳转日期 %@  = %@", timeStamp2, date2)


NSDate *currentDate = [NSDate date];//获取当前时间,日期

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"YYYY/MM/dd hh:mm:ss SS"];

NSString *dateString = [dateFormatter stringFromDate:currentDate];

NSLog(@"dateString:%@",dateString);




    if (!_isPhotoChat) {

        // 假设偏移表格高度的20%进行刷新

        if (!_isLoading) { // 判断是否处于刷新状态,刷新中就不执行

        

            // 取内容的高度:

            //    如果内容高度大于UITableView高度,就取TableView高度

            //    如果内容高度小于UITableView高度,就取内容的实际高度

            float height = scrollView.contentSize.height > self.chatTableView.frame.size.height ? self.chatTableView.frame.size.height : scrollView.contentSize.height;

            

            if ((height - scrollView.contentSize.height + scrollView.contentOffset.y) / height > 0.2) {

                // 调用上拉刷新方法

                NSLog(@"调用上拉刷新方法");

            }

            

            if (- scrollView.contentOffset.y / self.chatTableView.frame.size.height > 0.2) {

                // 调用下拉刷新方法

                NSLog(@"调用下拉刷新方法");

                _isLoading = YES;

                [self loadData2];

            }

        }

    }



  1.     //给图层添加背景图片:
             
  2.  //myView.layer.contents = (id)[UIImage imageNamed:@"view_BG.png"].CGImage;
              
  3. //将图层的边框设置为圆脚
      
  4. myWebView.layer.cornerRadius = 8;
       
  5. myWebView.layer.masksToBounds = YES;  
  6. //给图层添加一个有色边框
             
  7.  myWebView.layer.borderWidth = 5;
              
  8. myWebView.layer.borderColor = [[UIColor colorWithRed:0.52 green:0.09 blue:0.07 alpha:1] CGColor];

今天记录下 UILabel的高度和宽度自适应,方法特别简单

1 创建category 

.h

+ (CGFloat)getHeightByWidth:(CGFloat)width title:(NSString *)title font:(UIFont*)font;


+ (CGFloat)getWidthWithTitle:(NSString *)title font:(UIFont *)font;

.m

+ (CGFloat)getHeightByWidth:(CGFloat)width title:(NSString *)title font:(UIFont *)font

{


    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)];

    label.text = title;

    label.font = font;

    label.numberOfLines = 0;

    [label sizeToFit];

    CGFloat height = label.frame.size.height;

    return height;

}


+ (CGFloat)getWidthWithTitle:(NSString *)title font:(UIFont *)font {

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1000, 0)];

    label.text = title;

    label.font = font;

    [label sizeToFit];

    return label.frame.size.width;

}

2017-07-14 13:15:00 LOLITA0164 阅读数 19391
  • MyBatis 入门视频教程

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层框架。主要学会对数据库的增删改查

    12492 人正在学习 去看看 刘英杰

以下内容适用于旧版 Xcode(11以下),新版 Xcode 请参考最新内容:iOS 开发技巧 - 标注和 Code Snippets


引言

作为一只每天畅游在代码里而快(ku)乐(bi)的攻城狮,在一遍又一遍敲着重复的代码时候会不会觉得很无聊、浪费生命呢?即使使用了继承、分类、封装、宏定义等等一系列手段去优化代码、提高代码的复用性,但是对一些样式基本一致,再基础不过的代码,例如一些属性的定义,CGD,某控件的初始化(部分工厂化效果更好)等等,还是再一遍便的敲打出来,这是中折磨啊有没有?有人会说了,我可以复制原来的代码,再此基础上做改动啊。 没错是没错,但是Xcode有没有好的办法让我们方便的复用这些基本代码,不用我们手动复制呢?答案是有的,那就是今天要提的Code Snippets代码块。

系统代码块

其实系统已经帮我们定义好了一些代码块,例如你在使用for循环语句,switch选择语句,@protocol定义协议等等,就像下面一样:
这里写图片描述

系统还有很多这样便捷的代码块,你可以到这里去查看:
这里写图片描述

自定义代码块

  1. 选中你要存储的代码块,长按,待光标变成箭头时就可以拖动到Code Snippets里了。

  2. 编辑页面:

这里写图片描述

  1. 设置占位符(可选)
    如果你想制作一个模版,比如某个参数需要待定传入的,你可以在编辑页面使用<#站位代码/文字提示#>

  2. 使用
    在文件合适的地方敲出你设置的快捷代码,即可弹出:

这里写图片描述

如果使用了占位符就成了这样:
这里写图片描述

这样是不是方便了很多呢?

一些代码块

属性:

//1、strong:
@property (nonatomic,strong) <#Class#> *<#object#>;
//2、weak:
@property (nonatomic,weak) <#Class#> *<#object#>;
//3、copy:
@property (nonatomic,copy) NSString *<#string#>;
//4、assign:
@property (nonatomic,assign) <#Class#> <#property#>;
//5、delegate:
@property (nonatomic,weak) id<<#protocol#>> <#delegate#>;
//6、block:
@property (nonatomic,copy) <#returnType#>(^<#name#>)(<#arguments#>);

标注

// 分组
#pragma mark - <#添加注释#> 
// 注释
#pragma mark <#添加注释#> 
// MARK: <#注释内容#>
// TODO: <#实现某功能#>
// FIXME: <#修改内容#>
// !!!: <#添加注释#>
// ???: <#未知内容#>

代码片段备份

Xcode中的代码片段默认放在下面的目录中:

~/Library/Developer/Xcode/UserData/CodeSnippets

我们可以将目录中的代码片段备份,也可以将其直接拷出来放在不同的电脑上使用。

没有更多推荐了,返回首页