• 关于iOS放大模式

    2017-01-22 15:32:52
    近期有件很趣味性的问题:我们的一款App有张背景图,有640*960, 640*1136, 750*1334,1242*2208, 应该说该...开发把这个问题研究了老半天,区分了版本问题,切图问题,程序判断问题(这里实际也是存在问题的)一切可能

    近期有件很趣味性的问题:我们的一款App有张背景图,有640*960,  640*1136, 750*1334,1242*2208, 应该说该有的都有了。

    几乎所有的人测试都没有问题(可能大家也没关注这个问题,也许确实没有发生)。但是在我的iPhone 6s Plus上面就是不显示这个背景图。开发把这个问题研究了老半天,区分了版本问题,切图问题,程序判断问题(这里实际也是存在问题的)一切可能的根源后,确认说没法改,就我一个人发生了。

    在我眼中,什么问题的发生都是有他的依据的,不会凭空产生(系统级别的bug,哪么久恭喜你了,这都能碰上)。

    因此我就对开发说了4个字:放大模式

    iPhone 6 (S), iPhone 6 (S) Plus 都存在一个放大模式的效果,再放大模式下,iPhone 6 (S)分辨率为 640*1136 (同 5 系列), 而iPhone 6 (S) Plus为 1125*2001。

    开始我说的程序判断问题,先抛开网上已有的宏定义不说,我们的程序猿在判断过程中只有if,就没有一个else来结尾,从而导致了分辨率匹配不上,因此我的背景图也就是空白了。(从这点看出,程序逻辑上的容错性也是比较重要的,程序代码的健壮性问题这里就不讨论了

    希望从事iOS开发的同学们还是要多关注下每个新机型的诞生,带来了哪些新的变更(API,分辨率等等),会影响我们的App,从而作出应变措施(要不就连问题根源都不清楚的)。

    展开全文
  • iPhone6s更新至iOS13好用吗?3个月的亲身体验,感觉还能再战 iOS13的更新名单上竟然出现了iPhone6S这款手机,于是小酱就把自己的iPhone6S更新到了测试版,经历了3个月的亲身体验,小酱觉得自己的iPhone6S还能再战。 ...

    iPhone6s更新至iOS13好用吗?3个月的亲身体验,感觉还能再战

    iOS13的更新名单上竟然出现了iPhone6S这款手机,于是小酱就把自己的iPhone6S更新到了测试版,经历了3个月的亲身体验,小酱觉得自己的iPhone6S还能再战。
    在这里插入图片描述

    至于具体的上手体验如何,小酱来告诉你。
    深色模式,不能缺少

    【深色模式】是被网友一直讨论的话题之一,所以小酱第一个尝试的就是【深色模式】,iPhone6S完全支持,控制中心,重按亮度调节打开二级菜单,开启深色模式的按钮就在下方。
    在这里插入图片描述

    据可靠消息,苹果公司已经向开发者公布了深色模式的接口,但是我们经常使用的微信等手机应用目前还没有进行优化,不过iOS13正式版在20号才会正式推送,不知道推送后,这些应用的优化能够完成。
    在这里插入图片描述

    QuickPath输入功能

    iOS13版本中加入了QuickPath功能,让我们可以解锁另一种输入方式,我们只需要在键盘上轻轻滑动,便能够输入文字,对于习惯使用26键的用户来说,这种输入方法更方便。

    在这里插入图片描述
    声音调节栏位置变动

    这算是小酱比较满意的一个优化方案了,以后再也不用担心打游戏,看电视会遮挡住画面了。
    在这里插入图片描述

    以上这些都是iOS13赋予iPhone6S的新功能,那么iPhone6S搭载iOS13真的好用吗?

    小酱只想用八个字来简单的概括:日常使用,稍有卡顿。

    我们将照片缩小到年视图,然后再进行放大,滑动以及切换,能够发现不是太过于流畅。

    在这里插入图片描述
    当然这些卡顿,我们都可以用"他已经被使用四年了"这个理由而掩盖过去。没错的,一款已经使用了4年的手机,到现在还能够继续支持iOS13的更新,已经带给小酱惊喜了,更别说其它的了。

    在这里插入图片描述
    【小酱建议】

    如果你想体验新的系统以及新的功能,再半年内有着更换新机的打算,那么你还是可以尝试着去升级的;如果你还打算长久使用你的iPhone6S,那么就放弃选择升级吧,毕竟新的功能与长久使用相比,真的不值一提。

    在这里插入图片描述
    除了这些以外,iOS13好像依然不支持语音转文字的操作,我们需要从苹果应用商店内获取录音转文字助手,来完成此项操作。
    在这里插入图片描述

    iOS13设计本身就不是为iPhone6S量身定做的,像一些Face ID识别功能,你完全没有办法在iPhone6S上面得到更好的体验,所以有的时候提示的手机系统更新,其本质意义并不是让你更新系统,而是让你更新手机。

    在这里插入图片描述
    所以各位,你们是打算更新手机呢?还是打算更新系统呢?

    展开全文
  • 因为实习原因接触iOS开发,做了一周多点的时间,遇到了一个棘手的需求,也因此了解到了关于iPhone系列适配以及放大模式的有趣规律。 “特殊”的需求 当iPhone XS MAX/XR用户使用只适配了iPhone X/iPhone XS,并且...

    因为实习原因接触iOS开发,做了一周多点的时间,遇到了一个棘手的需求,也因此了解到了关于iPhone系列适配以及放大模式的有趣规律,涉及到了bounds与native bounds。

    “特殊”的需求

        当iPhone XS MAX/XR用户使用只适配了iPhone X/iPhone XS,并且隐藏了状态栏的app,同时没有启动放大模式且为竖屏时,进行UI处理。
        注:应用的适配是我无法决定的,处理的是一个独立于应用的悬浮窗的UI。只考虑竖屏。
    

    这样表述的需求其实有点绕,解释一下:
    1.当iPhone XS MAX/XR用户在放大模式运行应用,我们的UI不会出任何问题;
    2.当用户在标准模式运行应用,应用设置隐藏状态栏,UI没有问题;
    3.当用户在标准模式运行了只做了X/XS适配的(一般来说就是没有配launch image)应用,会出现UI被MAX“刘海”遮挡问题(其他情况下iPhone都能把UI往下推44单位)。
    总结下来,状态栏比较好确定,机型判断也不是问题,所以需求的核心是这样的:
    识别出应用只做了X/XS适配并且用户没有开启放大模式的情况。

    1. 识别出应用只做了X/XS适配 。这里的思路是读取[UIScreen mainScreen] bounds].size(以下简称bounds)的值。
    2. 用户有没有开启放大模式。当用户开启了放大模式,iPhone也会帮助我们完成UI调整,主要问题在于bounds在只做了低版本适配时的标准与放大模式有一样的值,需要使用native bounds来区分 。

    下面分开讲讲。

    注:6,6s,7,8具有一样的表现,以下统称6;6plus,6s plus,7plus,8plus具有一样的表现,以下统称6plus.

    bounds的表现

    在MAX上做了MAX/XR适配时bounds的值是414X896,只做了X/XS适配时的值是375X812。
    这个值是什么意思呢?

    @property(class, nonatomic, readonly) UIScreen *mainScreen;      // the device's internal screen
    

    这个是代码上对mainScreen的注释,bounds是他的一个属性。
    其实网上有很多资料说的更清晰,这个bounds其实就是“逻辑分辨率”,iPhone会把逻辑分辨率调整到“最适配”的数值上。

    适配的优先级:
    MAX/XR > X/XS >6plus>5>4 (机型==MAX/XR)
    X/XS>6>5>4 (机型==X/XS)
    6plus>5>4 (机型==6plus)
    6>5>4 (机型==6)
    以上均经过实机验证
    

    举例说明:
    1.如果你的设备是MAX,应用只适配了5,那么bounds的值就是5的逻辑分辨率320X568
    2.如果你的设备是X,应用适配了6和5,那么bounds的值就是6的逻辑分辨率375X667
    3.这里需要注意的是6和6plus只能二选一,这样看起来MAX/XR就像是X/XS的plus版本,但又有所不同
    总而言之bounds很好的体现了应用的适配情况。

    放大模式做了些什么

    实际上,当处于标准模式并且适配MAX/XR时,苹果会自动把我们的UI往下推,同时如果适配了比X更低版本时,表现也是没问题的。
    这让我怀疑要不就是我手里的UI对X有什么不可告人的处理,或者是苹果考虑少了MAX/XR在应用只适配X时的情况。
    抛开这些考虑还是要解决问题的,事情在加入了放大模式之后变得有些复杂,bounds变得不再可靠了。
    具体的场景就是,拿着一台MAX兴高采烈的打开一个只适配了X的竖屏游戏,结果最顶上的计分板被刘海遮住了,只要打开放大模式就解决了问题。
    程序员运行游戏打印了mainScreen的bounds值,结果发现标准模式和放大模式的bounds一样的
    为什么呢?
    那就要理解放大模式做了些什么:实际上是让整个机型变成了上一个版本的设备。

    MAX/XR -> X/XS //未验证
    X/XS 没有放大模式
    6plus ->6//千万注意不是5
    6 ->5
    6版本一下没有放大模式
    

    回忆一下,bounds是由适配的机型决定的。
    那么:
    放大模式优先于适配操作,这意味着你的MAX变成了X,然后进行了X的适配,这和MAX只做了X的适配是“逻辑”上一样的,因此bounds也相同了。

    Native Bounds究竟是什么

    这时候就需要一个不同于bounds的属性来区分在相同逻辑分辨率(相同的适配条件)下的标准和放大模式了。或许是运气查到了native bounds属性

    @property(nonatomic, readonly) CGRect nativeBounds;
    

    你要问我这个属性的真正意义,我会底气十分不足的说这个就是“物理分辨率”。
    为什么底气不足呢?因为它是会变的,这无疑和我们所理解的物理分辨率大相径庭。
    在完美适配的情况下,无论标准还是放大模式下native bounds都是设备的真正的物理分辨率(比如说MAX是1242X2688,X是1125X2436,6plus是1080X1920)。
    何谓之完美呢?你适配了当前机型和放大模式机型就叫做完美,这个时候标准模式用着当前机型的逻辑分辨率,而放大模式用着另一个机型的逻辑分辨率。
    这时候如果取消了当前机型的适配会出现什么后果呢?显然的一点是bounds会变的一样,而nativebounds的表现就直接看图吧。

    6标准模式 bounds native bounds
    适配6 375X667 750X1334
    适配5 320X568 640X1136
    适配4 320X480 640X960
    6放大模式 bounds native bounds
    适配6 320X568 750X1334
    适配5 320X568 750X1334
    适配4 320X480 750X1125

    这个图表基本完全说明了native bounds的表现规律。
    标准模式下,按照适配6的bounds同比例变化;
    放大模式下,按照适配5的bounds同比例变化。

    简要来说有这个结论,标准模式下和放大模式下,bounds相同时native bounds不会相同。
    嗯。不要和我说MAX和XR的事情,谢谢。

    问题的解决

    其实问题的根源在于MAX在面对只适配X的应用时的区别对待,如果能做到一视同仁,其实也就没有区分放大模式的必要了。
    最后需求的解决说简单也简单,把应用的bounds读出来,如果是X的逻辑分辨率那就再比较一下MAX标准模式下适配X时的native bounds,不相等就认为是放大模式了。
    这有个明显的隐患,native bounds是否能够一直维持其稳定性和唯一性?这显然不是苹果这一句话能让人放心的:

    The bounding rectangle of the physical screen, measured in pixels.
    

    具体还有一些其他判断和宏定义,对文章主要内容没有什么关联,就不放上来了。
    希望写明了自己遇到的问题、解决的方法以及思考(总感觉有更简单的方法。,。),可能有些地方更多是猜测,欢迎各位大佬指教。
    ————————————————————————————
    年前重新看了一次这篇文章,修改了一些描述,但是适配的问题究竟苹果做了没有还没有测试,反正我的处理方法算是经过时间考验了

    展开全文
  • 距离苹果WWDC发布会举行已久,苹果在昨日(9月18)开始向用户推送iOS 12 GM版,据称本次iOS的更新内容主要是性能方面的提升,打开相机的速度提升70%,屏幕键盘呼出速度提升50%,其它App启动速度提升2倍。下面让我们...

    距离苹果WWDC发布会举行已久,苹果在昨日(9月18)开始向用户推送iOS 12 GM版,据称本次iOS的更新内容主要是性能方面的提升,打开相机的速度提升70%,屏幕键盘呼出速度提升50%,其它App启动速度提升2倍。下面让我们看看究竟哪些设备将支持iOS 12 :
    在这里插入图片描述

    iOS 12 新特性

    ##1, 性能
    在这里插入图片描述
    据苹果介绍,iOS 12 将使得 iPhone 或 iPad 的操作更加快速和灵敏,比如应用启动速度最高提升 40%;键盘显示速度最高提升 50%,键盘调出的速度比以往更快,输入也更加灵敏;从锁屏界面中启动相机的速度最高提升 70%;高负载下 app 启动速度最高提升 2 倍。

    2,动话表情(Animoji)& 拟我表情(Memoji)

    在这里插入图片描述
    现在 iPhone X 及以上机型支持创建「拟我表情」,你可以通过选择皮肤、发型、头型、眼睛、眉毛等特征来创建自己的卡通形象,然后用在信息 app 或者 FaceTime 通话中。

    此外,动话表情(Animoji)还新增了四款形象,分别是霸王龙、幽灵、树袋熊、老虎。同时,现在动话表情最长支持录制 30 秒片段,而且拟我表情和动话表情均支持吐舌和眨眼识别。

    3,FaceTime 通话

    在这里插入图片描述
    在 iOS 12 上,FaceTime 变得更高效,也更有趣了。首先是「Group FaceTime 通话」群聊功能,这一功能最多支持 32 人同时进行通话,而且会自动放大正在说话中群聊成员的头像,当然你也可以通过点击某个成员的头像来放大。其次,现在 FaceTime 通话还支持动话表情和拟我表情,并且你可以在聊天过程中加入滤镜、文字效果、iMessage 信息贴纸包等。

    4,相机

    在这里插入图片描述
    现在在信息应用中,你可以通过用信息 app 内置的相机功能拍照,然后利用内置的特效和第三方贴纸包,以全新方式增强照片的效果。

    5,屏幕使用时间

    在这里插入图片描述
    作为苹果应对「数字成瘾」的方案,iOS 12 新增了「屏幕使用时间」功能。具体来说,这项功能通过统计你花在各个 app、网页浏览上的时间,以及接收通知和拿起手机的频率,让你能够系统地了解自己使用手机的习惯,进而帮助你合理安排花在设备上的时间。

    屏幕使用时间被放置在了系统设置中,你可以在这里查看今天或者过去七天的屏幕使用时间,其中分为「最常使用」「拿起次数」「通知」,同时你还可以设置:
    「停用时间」:设定时间远离屏幕,在停用期间,只有事先选择的应用和电话可以使用;
    「应用限额」:为需要管理的应用类别设定每日时间限额,应用的使用限额会在每天午夜还原;
    「始终允许」:始终允许的应用在停用期间也可使用;
    「内容和隐私访问限制」:阻止不当内容。

    在这里插入图片描述
    值得一提的是,这项功能的设置还可以在任何已登录 iCloud 的设备上启用,同时还可设置「家人共享」,以在家人的设备上使用「屏幕使用时间」。

    6,通知升级

    在这里插入图片描述
    iOS 12 还对通知中心进行了改动。现在来自同一应用的通知会被「折叠」显示,你可以通过点击来展开被折叠的通知,或者通过右划进入该应用,而左划则会出现三个选项:「隐式推送※」「关闭该应用的所有通知」「进入该应用的通知设置页面」。

    隐式通知会在通知中心显示,但不会在锁屏上显示,不会播放声音,不显示横幅,也不会在应用图标上出现标记。

    7,勿扰模式

    在这里插入图片描述
    优化勿扰模式,现在可以设置在 1 小时后、一天结束时、离开特定位置时或日历上的会议结束时,自动关闭勿扰模式;

    就寝时的勿扰模式,将自动调暗显示屏并将夜晚收到的通知静音,直至早上解锁 iPhone 为止。

    8,ARKit2

    在这里插入图片描述
    苹果为ARKit带来了一套全新的文件格式——USDZ,Adobe、Autodesk、Sketchfab、PTC、Quicxel等厂商后续均会陆续支持。

    在搭载 iOS 12 系统和 A9 芯片(或更高版本)的苹果设备上,新增了一个 AR 工具「测距仪」。该应用通过调用 iPhone 或 iPad 的摄像头,拉几根直线,就能从水平和垂直方向测量物体及表面,并可自动检测矩形物体的尺寸。

    同时 iOS 12 还加入对 ARKit 2 的支持,使得开发者可以创造出更身临其境的增强现实体验,并且支持多人模式。另外,还可以通过「信息」或「邮件」发送增强现实物体,然后在现实世界中观看。

    9,照片

    在这里插入图片描述

    在 iOS 12 中,照片应用新增了「为你推荐标签页」,其中分为「回忆」「精选照片」「共享建议」三个子标签。值得一提的是,iOS 12 的照片应用结合了最新的机器学习技术,能够通过识别照片中面孔来建议你将照片共享给其中的人物,而如果收到其他人共享的照片,设备会在你自己的照片图库中搜索同一个活动的照片,并建议你共享给发送者。

    另外,照片的搜索体验也变得更加完整,现在你能够通过地点、日程、多关键字等形式进行照片搜索。其他更新点还有:

    • 优化导入功能;
    • 支持 RAW 格式照片编辑(仅支持 iPhone SE、iPhone 6s/Plus 及以上机型);
    • 重新设计的相簿标签页

    10,Siri

    在这里插入图片描述

    Siri 现在可以做更多事情了,比如帮你自动整理相册里的照片,将几千张照片分门别类的整理好——是广州拍还是杭州拍的,拍的是喵星人还是汪星人,只需在相册里搜索一下关键词,马上就能得到答案。

    此外,Siri 加入了一项名为 Shortcuts(捷径)的功能,你可以在这个 app 中创建或定制命令,以便一次执行多个步骤。
    在这里插入图片描述

    11 ,Face ID

    苹果强化了 Safari 的安全性,那些会偷偷收集用户行为的网页将无所遁形。
    iPhone X 上市大半年来,独特的 Face ID 一直被用户疯狂吐槽「识别率不够高」、「安全没有保障」……
    为了解决这个问题,iOS 12 终于支持录入 2 个 Face ID——不过需要注意的是,这并不意味着你可以在一部 iPhone X 刷两个人的脸,录入两张完全不同的脸是没有用的,Face ID 只会识别第一次录入的人脸。

    12,其他内置应用

    iOS 12还对内置的应用进行了优化和改进,具体表现如下:

    • 钱包 app 如今可以绑定学生卡,不过目前仅支持 6 所大学
    • CarPlay 可以接入第三方 app,终于可以用高德地图导航了
    • 短信验证码现在支持自动填充了
    • 如果你用 iMessage 自拍,能够解锁漫画、水彩、水墨等各种特效滤镜

    开发新特性

    针对开发者,iOS 12又又哪些亮点值得关注呢?

    1,Auto Layout

    iOS12对AutoLayout做出了革命性的性能优化。此前,AutoLayout一直是业务开发中一大性能瓶颈,以至于部分app不得不忍痛舍弃对AutoLayout的使用来缓解掉帧等性能问题。而这些问题在iOS12之后很可能成为历史,具体的可以参考下面的链接:高性能Auto Layout

    2, 优化 App Assets

    在一个iOS app中,资源文件也是及其重要的一部分。如何在应用中通过使用assets达到最好的视觉效果和最高效的使用视图资源,也是每个开发者应该关注的部分。

    关于如何使用asset catalog来最优化的组织、优化、制作视图资源,如何更好的简化设计和开发人员之间工作流程。通过使用视图asset,可以提高应用的交付质量,占用更小的空间,受益到更多的用户。具体文章参考下面的链接:优化的App Assets

    3,Building Faster in Xcode

    除了iOS12运行上的性能提升,苹果还在最新发布的Xcode10上对构建速度与开发效率进行了优化。Xcode 10提高了构建速度和开发效率相关的新特性,从工具、环境、代码以及语言语法等多个方面介绍了加快构建速度的细节。通过了解Xcode在构建速度上的优化原理,开发者可以更好更高效地进行日常开发工作。具体可以参考下面的链接:更加快速的构建Xcode

    4,Swift

    WWDC2018发布了Swift 4.2版本。主打两方面的更新:一是关注提升开发人员生产力,开发者可以看到项目构建速度的提升和利于开发的语言改进;二是在二进制兼容性方面进行了大量的努力。可以参考下面的文章来了解Swift的新特性

    展开全文
  • IOS 应用开发简介 简单介绍了 IOS 工程文件, 界面设计文件, 按钮事件响应, 代码控制界面, 不同屏幕的图片适配




    一. iOS 项目简介


    1. iOS 文件简介



    创建一个 HelloWorld 项目, 在这个 IOS 项目中有四个目录 : 如下图;


    -- HelloWorldTests 目录 : 单元测试相关的类和资源;



    (1) HelloWorld 目录



    HelloWorld 目录介绍


    -- 命名规则 : 该目录名称与 IOS 项目名称相同, 是主目录;

    -- 存放内容 : IOS 项目的 源码文件, 界面设计文件, 资源文件都存放在该目录下;

    -- 源文件 : Objective C 的 .m 和 .h 后缀的文件;

    -- 界面设计文件 : Main.storyboard 是界面设计文件, 原来使用的是 nib 界面设计文件, storyboard 是新版本使用的;

    -- Supporting Files : 支持库, 一般保存 不是 Objective-C 的源代码资源文件;


    Supporting Files 目录简介


    -- HelloWorld-info.plist 文件 : 文件名格式为 项目名-info.plist, 属性列表文件, 保存 IOS 项目的各种信息;

    -- InfoPlist.strings 文件 : 该文件保存字符串, 主要为程序提供国际化支持;

    -- main.m 文件 : main() 函数程序入口文件;

    -- HelloWorld-Prefix.pch 文件 : 项目中用到的来自外部框架的头文件在这里面注明, Xcode 会预编译这些文件内容;




    (2) Frameworks 目录



    Frameworks 目录简介


    -- 包含文件 : 包含项目所依赖的框架 或者 库, 还有 声音 图像 等资源文件也可以放在该文件中;

    -- 自动链接 : 框架和库一旦被添加到该目录后, 会自动链接到应用中, IOS 应用可以调用这些资源 和 库中的类 和 函数;

    -- 系统默认框架 : Foundation.framework, CoreGraphics.framwork, UIKit.framework, CoreData.framework, XCTest.framework 五个默认框架;




    (3) Products 目录



    Products 目录


    -- 包含内容 : 包含该项目所生成的应用程序, 其中 HelloWorld.app 就是安装文件;

    -- 红色显示 : 由于还没有编译程序, 该文件显示红色, 这说明该文件目前不存在;



    (4) 目录对应



    Xcode 与 文件系统

    -- Xcode 逻辑分组


    -- 真实文件系统

    localhost:HelloWorld octopus$ tree
    .
    |____.DS_Store
    |____Base.lproj
    | |____.DS_Store
    | |____Main.storyboard
    |____en.lproj
    | |____.DS_Store
    | |____InfoPlist.strings
    |____HelloWorld-Info.plist
    |____HelloWorld-Prefix.pch
    |____HelloWorld.xcdatamodeld
    | |____.xccurrentversion
    | |____HelloWorld.xcdatamodel
    | | |____contents
    |____Images.xcassets
    | |____.DS_Store
    | |____AppIcon.appiconset
    | | |____Contents.json
    | |____LaunchImage.launchimage
    | | |____Contents.json
    |____main.m
    |____OCTAppDelegate.h
    |____OCTAppDelegate.m
    |____OCTDetailViewController.h
    |____OCTDetailViewController.m
    |____OCTMasterViewController.h
    |____OCTMasterViewController.m

    -- 不对应 : Xcode 导航面板中的目录 文件 与 真实文件系统中的目录文件不是对应的;

    -- 逻辑分组 : Xcode 将 真实文件进行了逻辑分组, 并不是真实的文件结构;

    -- 自定义分组 : 开发者还可以创建自定义的分组;


    mac 中的 tree 命令

    -- tree 命令模拟

    find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
    -- 模拟 tree 命令 : 之后可以调用 tree 命令了;

    alias tree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"




    2. Interface Builder 简介



    (1) 删除 Main.storyboard 文件



    删除 Main.storyboard 文件

    -- 删除方法 : 选择文件, 按 Delete 键, 弹出以下对话框, 选择 Move to Trash 选项, 直接删除;


    -- Remove Reference 选项 : 在文件系统保留该文件, 但是不编译该文件;

    -- 修改配置 : 点击项目名称, 选择 General 面板, 然后删除 Main Interface 中的 Main 选项;






    (2) 创建 xib 界面设计 文件



    创建 xib 文件流程

    -- 选择文件类型 : 菜单栏选择 File -> New -> File, 弹出下面对话框, 选择 iOS 的 User Interface 选项卡中的 View 选项, 点击 Next 按钮; 


    -- 创建文件 : 输入名称 Main.xib 自定义的, 选择分组 HelloWorld, 选择所输出的 app 文件;


    -- 创建成功





    (3) xib 界面设计 文件 简介





    xib 界面设计文件

    -- PlaceHolder 列表区 : 包括 File's Owner 和 First Responder 两个文件;

    -- Objects 列表区 : 保存界面布局文件中的 UI 控件实例;



    PlaceHolder 列表区

    -- File's Owner 文件 : 代表加载界面设计文件对象, 即 布局文件对象, 谁负责加载 Main.xib 界面设计文件, 谁就是该 界面设计文件的 File's Owner;

    -- First Responder 文件 : 代表正在与用户交互的对象, 即获取到焦点的对象, 其代表的控件会变化, 用户点击按钮时, 按钮就成为了其代表的控件;


    Objects 列表区

    -- 主要作用 : 该列表区 保存 xib 界面 所用到的 UI 控件实例;

    -- 工作流程 : 开发者将 UI 控件 拖入 xib 文件, app 运行时会加载 xib 文件, 并为每个控件都创建对象, Objects 列表区可以看到所有的 UI 控件;




    (4) xib 和 nib 文件



    xib 和 nib 后缀文件

    -- 新旧区别 : nib 后缀是传统格式, xib 后缀是新格式;

    -- 默认模板 : Xcode 默认使用 xib 作为默认格式;


    xib 与 nib 主要区别 :

    -- 文件类型 : xib 是文本文件, nib 是二进制文件, Xcode 编译项目时 会将 xib 文件转为 nib 文件; 

    -- nib 文件 : Interface Builder 把窗口, 菜单栏 以及 各种 UI 组件都冻结在 nib 文件中, 使用 nib 界面设计文件, 这些 UI 控件对象已经被创建好, app 运行时, 只需要苏醒这些 UI 控件 即可;

    -- xib 文件优点 : xib 更方便, 便于版本控制;





    3. nib 文件添加控件


    xib 添加控件

    -- 对象库面板快捷键 : 使用 control + option + command + 1 快捷键, 即可显示对象库面板;


    -- 添加 Label 控件 到界面中 : Label 拖到中间会有 水平 和 垂直两条 蓝色引导线;


    -- 边界引导线 : 如果把控件拖到边界, 会出现边界引导线, 说明不能再向外拖了;

    上 :   左 :   右 :     

    下 : 


    -- 显示 UI 控件轮廓 : Editor -> Canvas -> Show Layout Rectangles, 可以看到布局出现下面的轮廓;






    4. 控件属性修改相关面板




    相关面板

    -- 文件检查器面板 : 快捷键 option + command + 1, 文件相关信息;

    -- 快速帮助检查器面板 : 快捷键 option + command + 2, 显示先关的帮助文档;

    -- 身份检查器面板快捷键 option + command + 3, 管理界面控件的 实现类, 恢复 ID 等属性;

    -- 属性检查器面板 :快捷键 option + command + 4, 管理控件的 拉伸方式, 背景色 等外观属性;

    -- 大小检查器面板快捷键 option + command + 5, 管理控件 大小 位置 相关属性;

    -- 连接检查器面板 :  快捷键 option + command + 6, 管理控件 与 代码之间关联;





    4. UIView 属性



    UIView 属性 : 



    (1) Mode 属性



    Mode 属性 :


    -- 主要作用 : 用于控制 UI 控件内图片的对齐方式, 是否缩放适配控件;

    -- Scale To Fit : 缩放图片, 保证图片适配该控件;

    -- Aspect Fit : 保持纵横比缩放图片, 保证图片能够适应控件;

    -- Aspect Fill : 保持纵横比缩放图片, 保证图片能够填充控件;

    -- 注意 : 缩放会带来不必要的开销, 最好为不同屏幕尺寸创建对应的图片;





    (2) Tag 属性



    Tag 属性 : 该属性是 控件的 唯一标识, 可以根据该 标识 获取该 UI 控件的引用;



    (3) Interaction 属性



    Interaction 属性


    -- User Interface Enable : 勾选, 表明该控件支持与用户交互;

    -- Multiple Touch : 勾选, 表明该控件支持多点触控, 支持更复杂的手势;




    (4) Alpha 属性



    Alpha 属性


    -- 作用 : 用于控制该控件的透明度, 其属性支持 0.0 ~ 1.0 任意浮点数;

    -- 注意 : 如果设置为半透明效果, 会增加额外开销;




    (5) Background 属性



    background 属性


    -- 作用 : 设置控件的背景色;




    (6) Drawing 属性



    Drawing 属性


    -- Opaque : 设置控件是否为 不透明, 如果设置为不透明, 不管该控件的透明度是否是半透明, 该控件后的其它控件将不会被绘制;

    -- Hidden : 隐藏该控件, 用户看不到本控件;

    -- Clears Graphics Context : 清除该控件所覆盖的区域, 勾选该选项后 IOS 会清除该控件覆盖的区域, 然后绘制该控件, 会降低性能;

    -- Clip Subviews : 是否裁剪子控件, 当该控件包含多个子控件, 并且这些子控件超出了父类容器, 勾选后, 超出部分就不会被绘制;

    -- Autoresize Subviews : 是否自动调整子控件大小, 如果勾选, 该控件大小改变时, 其子控件也会随之调整大小;




    (7) Streching 属性



    Streching 属性 :


    -- 主要作用 : 用于控制 UIView 拉伸区域, 只有在需要调整控件大小并重绘控件时才需要定义拉伸区域;





    5. UILabel 属性



    UILabel 属性





    (1) Text 属性



    Text 属性


    -- 属性值 : 支持 Plain 和 Attribute 属性, 一般设置为 Plain;

    -- 文本 : 在 Text 属性下面有一个文本框, 在这个文本框中输入要显示的文本内容;




    (2) Color 属性



    Color 属性 : 控制 UILabel 中的文本颜色;




    (3) Font 属性



    Font 属性


     

    -- 作用 : 控制文本 字体 文字大小 风格等属性;

    -- System : 系统默认字体, 不能修改 Family Style Size 属性;

    -- System Bold : 系统默认的粗体字;

    -- System Italic : 系统默认的斜体字;



    (4) Alignment 属性



    Alignment 属性


    -- 作用 : 设置对齐方式, 左对齐, 居中对齐, 右对齐;



    (5) Lines 属性



    Lines 属性


    -- 作用 : 控制 文本行数;



    (6) Behavior 属性



    Behavior 属性


    -- Enabled : 控制 UILabel 是否可用, 如果没有勾选, 该 Label 不可用, 处于淡灰色;

    -- Highlighted : 控制 UILabel 是否处于高亮状态, 勾选该控件后处于高亮状态, 控件中的文本以高亮显示;




    (7) Line Break 属性



    Line Break 属性


    -- 作用 : 该属性对 UILabel 内的文本进行截断, UILabel 中的字符串比较多, UILabel 无法容纳这些字符串, 可以将字符串截断, 显示一部分;

    -- Truncate Head : 显示后半部分字符串, 前半部分使用 ... 代替;

    -- Truncate Middle : 显示 前后 部分, 中间使用 .. 替代;

    -- Truncate Tail : 截断后半部分, 后半部分使用 ... 替代;



    (8) AutoShrink 属性



    AutoShrink 属性




    -- 作用 : UILabel 中字符串较多 以至于 UILabel 无法容纳字符串时, AutoShrink 属性控制文本自动收缩;

    -- Fixed Font Size : 不缩放;

    -- Minimum Font Scale : 设置最小的缩放倍数, 设置的值是 0.0 ~ 1.0 之间的浮点数;

    -- Minimum Font Size : 设置最小的字号大小, 设置的值是字体大小;

    -- Tighten Letter Spacing : 勾选该复选框 会自动压缩字符串中的空白, 保证 UILabel 能容纳这些文本中的内容;




    (9) Highlighted 属性



    Highlighted 属性


    -- 作用 : 为 UILabel 中的文本设置高亮显示, 前提 Behavior 属性的 Highlighted 属性勾选;



    (10) Shadow 属性



    Shadow 属性


    -- 作用 : 为文本设置阴影颜色;




    (11) Shadow Offset 属性



    Shadow Offset 属性


    -- 作用 : 控制阴影文本与正常文本之间的偏移量, 

    -- Horizontal : 属性值 >0 向右偏移, < 0 向左偏移;

    -- Vertical : 属性值 >0 向下偏移, <0 向上偏移;








    二. IOS 中的 MVC 框架



    1. 程序入口




    (1) 程序入口代码



    程序入口代码示例

    //
    //  main.m
    //  FirstApp
    //
    //  Created by octopus on 15-11-4.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    #import "OCAppDelegate.h"
    
    int main(int argc, char * argv[])
    {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([OCAppDelegate class]));
        }
    }


    -- Main 函数执行流程调用 UIApplicationMain () 函数, 创建 UIApplication 对象, 为 UIApplication 对象设置委托, 负责处理应用程序事件循环;





    2. 应用程序委托




    (1) 委托对象简介



    委托对象简介

    -- UIApplication 本质 : UIApplication 代表了 IOS 应用程序, 每个应用中只有一个 UIApplication;

    -- 实际编程对象 : 虽然 UIApplication 代表了整个应用, 但是编程时不直接操作 UIApplication, 开发者一般与 delegate 委托对象交互;

    -- 全局变量 : UIApplication 委托对象全局可用, 定义全局变量即 将该变量设置为 UIApplication 的委托对象;

    -- 数据交换 : 获取委托对象, 可以向其中存取数据, 可以作为 IOS 应用的通信中心, 程序组件之间通过委托对象进行数据交互;

    -- 处理生命周期事件 : 应用程序委托对象还处理 IOS 应用的各种生命周期事件, 处理应用执行过程中的事件循环;




    (2) AppDelegate.h 详解



    OCAppDelegate.h 详解

    -- 代码示例

    //
    //  OCAppDelegate.h
    //  FirstApp
    //
    //  Created by octopus on 15-11-4.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface OCAppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    @end
    


    -- 继承父类 : 该 OCAppDelegate 类, 继承了 UIResponder 类, 表明该类可以作为响应者使用;

    -- 实现协议 : 实现了 UIApplicationDelegate 协议, 继承这个协议即表明该对象是应用程序委托类;

    -- UIWindow 属性 : 代表 IOS 应用程序的窗口, 一个应用只需创建一次 UIWindow 窗口;

    -- FKViewController 属性 : 代表视图控制器, 系统创建控制器时, 通常会加载对应的 xib 文件;

    -- 应用初始界面 : 在 OCAppDelegate 中定义了 FKViewController 变量, 该变量类型对应的 xib 文件就是初始界面;




    (3) AppDelegate.m 详解



    AppDelegate.m 详解

    -- 代码示例 : 书中的示例代码;

    //
    //  FKAppDelegate.m
    //  HelloiOS
    //
    //  Created by yeeku on 13-5-16.
    //  Copyright (c) 2013年 crazyit.org. All rights reserved.
    //
    
    #import "FKAppDelegate.h"
    
    #import "FKViewController.h"
    
    @implementation FKAppDelegate
    // 当应用程序启动后将会调用该方法
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    	// 创建UIWindow对象,并初始化该窗口的大小与主屏幕大小相同
    	// 程序将创建的UIWindow对象赋值给该程序委托对象的window属性
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // 创建FKViewController对象、并使用FKViewController界面布局文件来
    	// 初始化该视图控制器关联的用户界面
    	self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];
    	// 让该程序的窗口加载、并显示viewController视图控制器关联的用户界面
    	self.window.rootViewController = self.viewController;
    	// 将该UIWindow对象设为主窗口、并显示出来
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
    	// 当应用程序从活动状态转入不活动状态时,系统将会调用该方法。
    	// 通常来说的,当应用程序突然被中断(比如有电话、短信进来时),系统将会回调该方法
    	// 另外,当用户离开该程序,程序开始转入后台状态时也会回调该方法。
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
    	// 通常可通过重写该方法来释放共享资源、保存用户数据,取消定时器。
    	// 开发者还可通过该方法来保存足够的状态数据,
    	// 这样保证用户重新启动该应用时能正确恢复到当前状态
    	// 如果该应用程序支持后台执行,当用户退出时,系统调用调用该方法,而不是调用
    	// applicationWillTerminate:方法
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
    	// 当应用程序将要进入前台时将会调用该方法。
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
    	// 当应用程序进入前台、并转入活动状态时将会调用该方法。
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
    	// 当应用程序被终止时,系统将会调用该方法。
    }
    
    @end
    

    -- 重写 application 方法 : 应用程序加载时会回调该方法;


    application 方法流程

    -- 创建 UIWindow 对象 : 创建 UIWindow 对象, 该对象就是 IOS 应用程序的窗口;

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    -- 创建 ViewController 对象 : 该对象用于加载该对象对应的 xib 等界面设计文件;

    self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];

    -- 显示界面 : 让应用程序窗口显示 ViewController 对象;

    self.window.rootViewController = self.viewController;

    -- 主窗口 : 将该程序的窗口设置为主窗口, 将主窗口显示出来;

    [self.window makeKeyAndVisible];





    3. IOS 的 MVC 模式 - M(Model 模型) V (View 视图) C (Controller 控制器)



    IOS MVC 模式

    -- Model 模型 : Model 一般式普通的 Objective - C 类, 这些类用于保存 处理 数据;

    -- View 视图 : 使用 Interface Builder 创建的视图组件, 如 xib, storyboard 后缀的界面设计文件;

    -- Controller 控制器 : 一般是 Objective - C 类, 一般都会继承 UIViewController 基类;




    4. UIViewController 控制器




    UIController 方法详解 : 主要用于处理视图加载, 显示等事件;

    -- viewDidLoad 方法 : 视图装载完成后, 自动回调该方法, 重写时注意先使用 [super viewDidLoad] 把父类方法调用了, 在其后追加自己处理的内容;

    -- didReceiveMemoryWarning 方法 : 系统自动回调的, 内存紧张时会调用此方法, 在方法内释放内存, 注意先调用 [super didReceiveMemoryWarning] 方法;

    -- viewWillAppear 方法 : 视图将要显示时系统会自动回调该方法;

    -- viewDidAppear 方法 : 视图显示出来后系统自动回调的方法;

    -- viewWillDisappear 方法 : 视图将要被隐藏 或者 关闭时, 回调该方法;

    -- viewDidDisappear 方法 : 视图被隐藏 或 关闭后, 回调该方法;

    -- viewWillLayoutSubviews 方法 : 视图将要排列其子视图时, 需要回调的方法;

    -- viewDidLayoutSubviews 方法 : 视图已经排列好其子视图后, 回调的方法;


    UIViewController 代码示例

    -- 头文件

    //
    //  OCViewController.h
    //  FirstApp
    //
    //  Created by octopus on 15-11-4.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface OCViewController : UIViewController
    
    @property (strong, nonatomic) IBOutlet UILabel *label1;
    @property (strong, nonatomic) IBOutlet UILabel *label2;
    @property (strong, nonatomic) IBOutlet UIButton *button;
    - (IBAction)button_click:(id)sender;
    
    @end
    


    -- 实现文件

    //
    //  OCViewController.m
    //  FirstApp
    //
    //  Created by octopus on 15-11-4.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import "OCViewController.h"
    
    @interface OCViewController ()
    
    @end
    
    @implementation OCViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        
        //使用 IBOutlet 获取 UI 控件
        [self.label1 setText:@"Tom"];
        
        //使用 tag 获取 UI 控件
        UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
        [label_tag setText:@"Jerry"];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (IBAction)button_click:(id)sender {
        //使用 IBOutlet 获取 UI 控件
        [self.label1 setText:@"John"];
        
        //使用 tag 获取 UI 控件
        UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
        [label_tag setText:@"John"];
    }
    @end
    







    三. IOS 中的 事件机制



    1. 通过 IBOutlet 连接获取控件




    (1) IBoutlet 属性



    IBOutlet 属性

    -- 主要作用 : IBOutlet 属性可以连接 Objective - C 源码 和 界面设计文件 (.xib 文件 或 .storyboard 文件);

    -- 连接方法 : 在界面设计文件对应的 UIViewController 类中, 定义一个 IBOutlet 属性, 该属性 与 Interface Builder 中的控件相关联;

    -- 调用方法 : 在 UIViewController 中调用 控件的方法, 使用 IBOutlet 属性即可访问 界面设计文件的组件;



    (2) IBoutlet 连接步骤



    IBOutlet 连接方法

    -- 打开辅助编辑器


    -- 辅助编辑器界面 : 左边显示 界面设计文件, 右边显示 UIViewController 类;


    -- 拖动控件到 UIViewController 中 : 按住 control 键, 将控件拖到 UIViewController.h 中;


    -- 设置 IBOutlet 的属性 : 控件拖到 UIViewController 中后, 弹出下面的对话框;


    -- 连接控件 : 点击上面的 Connect, 在 UIViewController 中就会出现 @property IBOutlet 属性;

    //
    //  OCViewController.h
    //  FirstApp
    //
    //  Created by octopus on 15-11-4.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface OCViewController : UIViewController
    
    @property (strong, nonatomic) IBOutlet UILabel *label1;
    @property (strong, nonatomic) IBOutlet UILabel *label2;
    @property (strong, nonatomic) IBOutlet UIButton *button;
    - (IBAction)button_click:(id)sender;
    
    @end
    



    -- IBOutlet 连接标识 : 如下图, 属性前面有 圆圈黑点, 即说明 该 属性是连接 UI控件 的;






    (3) IBoutlet 属性解析



    IBOutlet 属性解析

    -- Connection : 设置该控件的 IBOutlet 或 IBOutlet 集合, 默认 IBOutlet 属性;

    -- Name : 属性名, 即 @property 的属性名;

    -- Type : 界面控件的类型, UILabel 等控件名称;

    -- Storage : Weak, Strong 指针的强 弱 存储机制;




    (4) IBoutlet 关联查看



    IBOutlet 属性

    -- 不使用 @synthesize : 使用 @property 定义的属性, 在 UIViewController.m 中不需要 使用 @synthesize 设置 setter getter 方法;

    -- 查看连接关系 : 使用 Xcode 的连接检查器面板查看 IBOutlet 属性 与 UI控件 间关联, 使用 control + option + command + 6 或者 右上角的  图标 , 注意 要在界面设计文件中先选择 File Owner;




    解析连接器面板中的 IBOutlet 元素


    -- Outlets : 多个 IBOutlet 属性, 每个属性都对应 界面设计文件中的一个 UI 控件;

    -- Referencing Outlets : 代表被选择对象本身被关联到其他对象的 IBOutlet 属性;

    -- Referencing Outlets Collections : 控件被关联到其它对象的 IBOutlet 集合属性;




    2. 通过 Tag 属性获取控件




    (1) Tag 获取属性简介



    通过 Tag 属性获取控件流程

    -- 设置 UILabel 控件的 Tag 属性 : Command + option + 4 即可显示属性界面;



    -- 获取 UILabel 控件 : 通过 viewWithTag : tag标签 获取 UI 控件的引用; 

        //使用 tag 获取 UI 控件
        UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
        [label_tag setText:@"Jerry"];




    3. IBAction 绑定实现事件处理




    (1) IBAction 简介



    IBAction 简介

    -- 主要作用 : IBAction 是 UIViewController 中的特殊方法, 这该方法是 UI 控件事件处理方法;


    IBAction 事件绑定流程

    -- 需求 : 为UIButton 组件添加点击方法; 

    -- 创建 UI 组件 : Interface Builder 中创建 UIButton 对象;

    -- 创建 IBAction 方法 : 在 界面设计文件 对应的 UIViewController 中定义 IBAction 方法;

    -- 绑定 IBAction 方法与 UI 组件 : 将 UIViewController 中的 IBAction 方法 与 界面设计文件中的 UIButton 组件绑定;

    -- 触发 IBAction 方法界面中的 UIButton 被点击, 就会回调 IBAction 方法;




    (2) IBAction 绑定步骤



    IBAction 绑定步骤

    -- 选中界面设计文件, 打开辅助编辑器


    -- 拖动按钮到 UIViewController.h 文件中 : 按住 control 键不放, 将按钮拖动到 UIViewController 中;


    -- 设置 IBAction 属性 : 在接下来弹出的对话框中的 Connection 列表设置 为 Action, 将设置 IBAction 属性, 设置完毕后会自动生成点击事件回调方法, 之后在实现类中实现这个方法即可;




    (3) IBAction 属性详解



    IBAction 属性


    -- Connection : 选择为 UI 控件创建 IBOutlet 还是 IBAction 属性类型;

    -- Name : IBAction 方法名;

    -- Type : 触发该事件的 UI 控件类型, 默认为 id, 如果需要更精准可以设置成具体的 UI 组件类, 如 UIButton;

    -- Event : 选择为什么样的事件绑定 IBAction 属性, 默认 Touch Up Inside 在 UI 控件区域按下并松开;

    -- Arguments : 选择 IBAction 方法形参列表, Sender 触发 IBAction 方法的事件源, Sender And Event, Event 是事件本身;




    4. 通过代码设置事件处理方法




    (1) 注册删除事件响应方法


    注册删除事件响应方法

    -- 注册删除事件方法来源 : IOS 中与用户交互的控件都继承了 UIControl 类, 注册 删除 控件响应方法 是该 UIControl 基类提供的;

    -- 添加事件响应方法 : "addTarget : action : forControlEvents :" , 为当前控件的 指定事件 设置 处理方法;

    -- 移除事件响应方法 : "removeTarget : action : forControlEvent : " , 删除 UIControl 指定的事件处理方法.




    (2) 注册删除事件响应方法参数解析



    添加移除事件方法参数解析

    -- addTarget / removeTarget 参数 : 指定 事件响应方法 所在的对象;

    -- action 参数 : 接受一个 SEL 参数, 该 参数代表的方法作为事件处理方法;

    -- forControlEvents 参数 : UIControlEvent 枚举值参数, 用于指定事件类型.



    (3) 代码示例



    代码示例

    -- OCViewController.h 头文件 : 声明 IBOutlet 指定 UI 控件引用;

    @property (strong, nonatomic) IBOutlet UIButton *UIControl_button;

    -- OCViewController.m 文件 : 为 UI 控件添加事件监听;

        //注意 selector 中的方法, 如果后面有参数 则需要带上 冒号 ":"
        [self.UIControl_button addTarget: self action:@selector(button_click2:) forControlEvents: UIControlEventTouchUpInside];

    -- 添加的方法

    - (void) button_click2:(id)sender{
        [self.label1 setText:@"octopus"];
        [self.label2 setText:@"octopus"];
        
    }





    四. StoryBoard 介绍



    1. StoryBoard 简介




    StoryBoard 简介

    -- 使用版本 : IOS 5 之后默认使用 storyboard 作为界面设计文件, 而之前是 xib 作为默认的界面设计文件;

    -- 与 xib 界面设计文件的共同点 : 项目中主要包含 应用委托类, 界面设计文件, 界面控制类, 如下图 : 


    -- 不同点 : UIViewController 与界面设计文件的名称不再相同, 界面设计文件名称是 Main.storyboard, 该界面设计文件包含所有的界面;

    -- 界面设计文件 与 界面控制类对应关系 : 一个 storyboard 界面设计文件 对应 多个 界面控制类;




    2. StoryBoard 与 xib 区别详解




    (1) Scence 概念



    Scene 场景简介

    -- Scene 组成 : Scene 由 整个视图, 视图控制器, 第一响应者 组成;

    -- 场景与界面 : 一个场景 对应 一个窗口界面; 

    -- 层次关系 : View Controller 在 Scene 中, UI 控件 在 View Controller 中, 如下图 : 




    (2) 灰色箭头



    灰色箭头作用

    -- 作用 : 箭头表示 UI 控制器之间的切换关系, 箭头指向需要加载的 视图控制器;

    -- 移动箭头 : 视图中只有一个 UI 控制器, 移动箭头始终指向唯一的 一个 UI 控制器;

    -- 好处 : 可以直观地看到多个视图之间的协作关系, 可以在 Interface Builder 中配置视图之间的切换关系;

    -- 图示






    (3) 工具图标




    界面设计文件的 工具图标

    -- 缩小 : 多个视图控制器在同一个窗口, 缩小界面可以同时查看所有的 视图控制器;

    -- 恢复 : 恢复原样查看;

    -- 放大 : 放大界面设计文件;







    3. AppDelegate 委托类对比





    委托类代码对比

    -- xib 委托类 : 加载完成方法;

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    	// 创建UIWindow对象,并初始化该窗口的大小与主屏幕大小相同
    	// 程序将创建的UIWindow对象赋值给该程序委托对象的window属性
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // 创建FKViewController对象、并使用FKViewController界面布局文件来
    	// 初始化该视图控制器关联的用户界面
    	self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];
    	// 让该程序的窗口加载、并显示viewController视图控制器关联的用户界面
    	self.window.rootViewController = self.viewController;
    	// 将该UIWindow对象设为主窗口、并显示出来
        [self.window makeKeyAndVisible];
        return YES;
    }


    -- storyboard 委托类 : 加载完成方法;

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.
        return YES;
    }

    -- 主要区别 : storyboard 不需要创建 UIViewWindow  和 UIViewController, 不需要将 UIViewController 添加到 UIWindow 中;

    -- 设置 storyboard : 点击 项目选项 , 在 General 选项卡中, 选择左侧 TARGETS, 选中对应项目, 在 Main Interface 中选择 storyboard 界面设计文件;







    五. 代码控制 UI 界面



    1. 代码生成 UI 界面




    (1) 代码生成 UI 界面示例



    基本无界面 UI 显示代码示例

    -- 创建 Empty Application


    -- OCAppDelegate.h

    //
    //  OCAppDelegate.h
    //  Empty
    //
    //  Created by octopus on 15-11-19.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface OCAppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    @property (strong, nonatomic) UILabel * label;
    
    @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
    @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
    @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    
    - (void)saveContext;
    - (NSURL *)applicationDocumentsDirectory;
    
    @end

    -- OCAppDelegate.m

    //
    //  OCAppDelegate.m
    //  Empty
    //
    //  Created by octopus on 15-11-19.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import "OCAppDelegate.h"
    
    @implementation OCAppDelegate
    
    @synthesize managedObjectContext = _managedObjectContext;
    @synthesize managedObjectModel = _managedObjectModel;
    @synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
    @synthesize label;
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // 创建 UIWindow 对象, 设置其大小与屏幕大小相同
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // 设置背景颜色
        self.window.backgroundColor = [UIColor whiteColor];
        
        // 创建 UIViewController 对象
        UIViewController * controller = [[UIViewController alloc] init];
        // 窗口加载并显示 视图控制器 并 关联 用户界面
        self.window.rootViewController = controller;
        // 创建 UIView 对象
        UIView * rootView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // UIViewController 显示 rootView 控件
        controller.view = rootView;
        
        // 创建圆角按钮
        UIButton * button = [UIButton buttonWithType : UIButtonTypeRoundedRect];
        // 设置按钮大小
        button.frame = CGRectMake(60, 200, 200, 40);
        // 为按钮设置文本
        [button setTitle:@"octopus button" forState: UIControlStateNormal];
        // 为按钮添加点击事件
        [button addTarget:self action:@selector(button_click) forControlEvents:UIControlEventTouchUpInside];
        // 将按钮添加到 View 上
        [rootView addSubview : button] ;
        
        // 创建 UILabel 对象
        label = [[UILabel alloc] initWithFrame:CGRectMake(60, 30, 200, 130)];
        // 设置文本内容
        label.text = @"octopus label";
        // 设置背景颜色
        label.backgroundColor = [UIColor grayColor];
        // 将 UILabel 添加到 rootView 中
        [rootView addSubview : label];
        
        
        // 显示 界面
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void) button_click
    {
        [label setText:@"button click"];
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Saves changes in the application's managed object context before the application terminates.
        [self saveContext];
    }
    
    - (void)saveContext
    {
        NSError *error = nil;
        NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
        if (managedObjectContext != nil) {
            if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
                 // Replace this implementation with code to handle the error appropriately.
                 // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            } 
        }
    }
    
    #pragma mark - Core Data stack
    
    // Returns the managed object context for the application.
    // If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
    - (NSManagedObjectContext *)managedObjectContext
    {
        if (_managedObjectContext != nil) {
            return _managedObjectContext;
        }
        
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator != nil) {
            _managedObjectContext = [[NSManagedObjectContext alloc] init];
            [_managedObjectContext setPersistentStoreCoordinator:coordinator];
        }
        return _managedObjectContext;
    }
    
    // Returns the managed object model for the application.
    // If the model doesn't already exist, it is created from the application's model.
    - (NSManagedObjectModel *)managedObjectModel
    {
        if (_managedObjectModel != nil) {
            return _managedObjectModel;
        }
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Empty" withExtension:@"momd"];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
        return _managedObjectModel;
    }
    
    // Returns the persistent store coordinator for the application.
    // If the coordinator doesn't already exist, it is created and the application's store added to it.
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
        if (_persistentStoreCoordinator != nil) {
            return _persistentStoreCoordinator;
        }
        
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Empty.sqlite"];
        
        NSError *error = nil;
        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            /*
             Replace this implementation with code to handle the error appropriately.
             
             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
             
             Typical reasons for an error here include:
             * The persistent store is not accessible;
             * The schema for the persistent store is incompatible with current managed object model.
             Check the error message to determine what the actual problem was.
             
             
             If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
             
             If you encounter schema incompatibility errors during development, you can reduce their frequency by:
             * Simply deleting the existing store:
             [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
             
             * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
             @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
             
             Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
             
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }    
        
        return _persistentStoreCoordinator;
    }
    
    #pragma mark - Application's Documents directory
    
    // Returns the URL to the application's Documents directory.
    - (NSURL *)applicationDocumentsDirectory
    {
        return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    }
    
    @end
    

    -- 执行效果 : 点击前;



    -- 执行后


    -- 工程内容 : 该工程中只需要修改 OCAppDelegate.h 和 OCAppDelegate.m 两个类;







    2. 动态添加删除组件




    (1) 代码示例



    动态添加删除组件代码示例

    -- 创建文件 : 创建 Single View Application;


    -- 工程文件显示 : 只需要修改 OCViewController.m 文件即可, 其它文件原封不动;


    -- OCViewController.m 代码

    //
    //  OCViewController.m
    //  DynamicUI
    //
    //  Created by octopus on 15-11-22.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import "OCViewController.h"
    
    /*
        类别与扩展
        类别 : 为现有类添加新方法, @interface 已有类 (类别名) ... 方法 ... @end, 实现类实现接口中的方法.
        -- 头文件名称 : 已有类+类别名.h;
        -- 实现类文件名称 : 已有类+类别名.m, 注意 该实现部分 只是实现 类别中定义的内容;
     
        扩展 : 扩展是匿名的类别, 扩展也要定义的 已有类+任意名.h 中, 在实现类 已有类.m 中需要实现 已有类接口中的内容, 也需要实现扩展中定义的抽象类.
     */
    // OCViewController 的扩展, 在
    @interface OCViewController ()
    
    @property (nonatomic, strong) NSMutableArray * labels;
    
    @end
    
    @implementation OCViewController
    
    int nextY = 80;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        
        // 设置 View 的背景颜色
        self.view.backgroundColor = [UIColor grayColor];
        // 初始化 数组
        self.labels = [NSMutableArray array];
        // 创建按钮
        UIButton * button_add = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        // 设置按钮位置大小
        button_add.frame = CGRectMake(30, 30, 60, 40);
        // 设置按钮 平时状态的 文本, 可以设置平时状态时的文本
        [button_add setTitle:@"添加 Label" forState : UIControlStateNormal];
        // 设置按钮点击事件
        [button_add addTarget:self action:@selector(addButton) forControlEvents:UIControlEventTouchUpInside];
        // 将按钮添加到布局中
        [self.view addSubview:button_add];
        
        // 生成删除按钮
        UIButton * button_delete = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        // 设置按钮的位置大小
        button_delete.frame = CGRectMake(230, 30, 60, 40);
        // 设置按钮文本
        [button_delete setTitle:@"删除 Label" forState:UIControlStateNormal];
        // 设置按钮点击事件
        [button_delete addTarget:self action:@selector(deleteButton) forControlEvents:UIControlEventTouchUpInside];
        // 将按钮添加到布局中
        [self.view addSubview:button_delete];
    }
    
    // 添加控件方法
    - (void) addButton
    {
        // 生成一个 UILabel 控件
        UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(80, nextY, 160, 30)];
        // 给控件设置文字
        label.text = @"Label 控件";
        // 将控件添加到集合中
        [self.labels addObject:label];
        // 将控件设置到布局中
        [self.view addSubview:label];
        // y 坐标自增
        nextY += 50;
    }
    
    // 删除控件方法
    - (void) deleteButton
    {
        // 删除的前提是控件个数大于 0
        if([self.labels count] > 0){
            // 将集合中的最后一个 UILabel 控件从布局中删除
            [[self.labels lastObject] removeFromSuperview];
            // 将 UILabel 控件从集合中删除
            [self.labels removeLastObject];
            // y 坐标自减, 用于添加控件使用
            nextY -= 50;
        }
    }
    
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    

    -- 演示效果






    3. 自定义 UI 控件




    (1) 自定义组件简介



    自定义组件简介

    -- UIView 基类 : 所有的 UI 控件都继承了 UIView 基类, UI 组件在 UIView 提供的空白区域上绘制具体的细节;

    -- 适用情况 : 在 IOS 系统提供的组件不满足需求时, 就需要自定义组件;



    (2) UIView 基类常用方法



    UIView 基类常用方法简介

    -- "initWithFrame :" 方法 : UI 控件初始化方法, 用于对 UI 控件额外初始化操作时使用;

    -- "initWithCoder :" 方法 : 界面设计文件中加载完该控件后, 自动调用的方法;

    -- "drawRect : " 方法 : 自行绘制控件内容, 重写该方法, 在该方法中实现;

    -- "layoutSubviews : " 方法 : 精确控制子控件布局;

    -- "addAddSubviews : " 方法 : 添加完子控件后回调的方法;

    -- "willRemoveSubview : " 方法 : 将要删除子控件时, 回调该方法;

    -- "didMoveToSuperview : " 方法 : 把控件添加到父控件完成时 回调该方法;

    -- "willMoveToSuperview : " 方法 : 在将要添加到父控件之前, 回调该方法;

    -- "didMoveToWindow : " 方法 : 将控件添加到窗口完成时, 回调该方法;

    -- "willMoveToWindow : " 方法 : 将控件添加到窗口之前, 回调该方法;

    -- "touchesBegan : withEvent : " 方法 : 开始触摸控件时触发的方法;

    -- "touchesMoved : withEvent : " 方法 : 手指在控件上移动回调方法;

    -- "touchesEnd : withEvent : " 方法 : 手指结束触摸回调方法;

    -- "touchesCanceled : withEvent : " 方法 : 取消触摸回调方法;




    (2) 自定义组件示例



    自定义组件 流程 及 代码示例

    -- 创建 SingleViewApplication


    -- 查看 Main.storyboard 的控件 : 点击 界面设计文件中的 UIView 根控件, 使用 command + option + 3 打开身份检查器, 由身份检查器上可以看到 其 Custom Class 属性为 UIView, 因此该界面的根控件时 UIView;


    -- 创建自定义类 : 选择菜单中的 File -> New File -> Cocoa Touch -> Objective-C Class;


    -- OCFollowTouchView.h 代码

    //
    //  OCFollowTouchView.h
    //  FollowTouch
    //
    //  Created by octopus on 15-11-25.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface OCFollowTouchView : UIView
    
    @end
    


    -- OCFollowTouchView.m 代码示例

    //
    //  OCFollowTouchView.m
    //  FollowTouch
    //
    //  Created by octopus on 15-11-25.
    //  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
    //
    
    #import "OCFollowTouchView.h"
    
    @implementation OCFollowTouchView
    
    int currentX;
    int currentY;
    
    - (void) touchesMoved : (NSSet * ) touches withEvent:(UIEvent *)event
    {
        //获取 UITouch 对象
        UITouch * touch = [touches anyObject];
        //获取触摸的位置
        CGPoint lastPoint = [touch locationInView:self];
        currentX = lastPoint.x;
        currentY = lastPoint.y;
        //重绘 UI 控件
        [self setNeedsDisplay];
    }
    
    - (void) drawRect:(CGRect)rect
    {
        //获取绘图上下文对象
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //设置所绘制的图像为红色
        CGContextSetFillColorWithColor(ref, [[UIColor redColor] CGColor]);
        //绘制图像
        CGContextFillEllipseInRect(ref, CGRectMake(currentX - 10, currentY - 10, 20, 20));
    }
    
    @end
    

    -- 将自定义组件设置到 Main.storyboard 中 : 在 Custom Class 属性中, 输入自定义类, 然后点击回车, 默认的 View 就会变成我们设置的自定义类;



    -- 演示效果






    六. UI 图片


    参考文章

    -- IOS 图标图形http://www.zhihu.com/question/20248971 ;

    -- IOS 7 官方推荐尺寸 : http://www.cnblogs.com/dyllove98/p/3233845.html ;

    -- IOS 8 官方推荐尺寸点击打开链接 ;

    -- 图标图像大小 : http://www.cnblogs.com/dyllove98/p/3233845.html ;



    1. IOS 图片规格




    (1) Retina 视网膜屏



    Retina 屏幕简介

    -- 像素 : 高清晰度的视网膜屏幕, 这种屏幕的分辨率是普通非 Retina 屏幕的 2 倍;

    -- 市场状况 : 目前 IOS 已经下架了所有的 非 Retina 屏幕的设备, 目前在售的所有设备都是 Retina 设备, 但是之前卖出的许多设备有些不是 Retina 屏幕的;

    -- 支持 Retina 屏幕的设备 : 现在在售的所有设备, iphone4 ~ 6S, ipod4, ipad 2 之后的新设备;

    -- 不支持 Retina 屏幕设备 : 之前出售的低端 IOS 设备大都是非 Retina 屏幕的, ipod 1, ipod2, ipod3, iphone, iphone3G, iphone3GS, ipad1, ipad2.

    -- 素材命名规范 : 非 Retina 屏幕名称为 pictire.png, Retina 屏幕的图片名称是 picture@2x.png;




    (3) 圆角矩形



    圆角矩形圆角

    -- 512 px : 90 px;

    -- 114 px : 20 px;

    -- 72 px : 12 px;

    -- 57 px : 10 px;

    -- 58 px : 10 px;

    -- 29 px : 9 px;




    (3) 应用图标规格



    Retina 屏幕应用图标规格

    -- iPhone 4S ~ 6 (Retina @2x) : 120 x 120 ;

    -- iPhone6 Plus (Retina @3x) : 180 x 180;

    -- iPad 和 iPad Mini (Retina @2x) : 152 x 152 ;


    非 Retina 屏幕应用图标规格

    -- iPad 和 iPad Mini (@1x) : 76 x 76 ;

    -- iPhone 和 iPod : 57 x 57;



    (4) 启动界面像素




    Retina 屏幕启动画面

    -- iPhone 5 ~ 6 : 640 x 1136;

    -- iPhone 4 ~ 4S : 640 x 960;

    -- iPad : 1536 x 2048 (纵向), 2048 x 1536 (横向);;


    非 Retina 屏幕启动图片

    -- iPad2 或 iPad Mini : 768 x 1024 (纵向), 1024 x 768 (横向);




    2. IOS 图标设置




    IOS 图片设置 : 直接从文件目录将图片拖动到 Xcode 相应的设置中.

    -- 设置图标 : 在项目文件视图中, 点击 Images.xcassets, 选中左侧的 AppIcon 设置应用图标, 如下图;


    -- 设置启动图片




    展开全文
  • UI规范: iOS: 屏幕大小(单位为像素px): 4、4s:640*960 @2x 5、5s、5c:640*1136 @2x ...放大模式:1125*2001(即6的1.5倍) @3x 关于 .png、@2x.png、@3x.png的关系: 可以理解为屏幕上的点对应的像素多少。
  • iPhone6/6S的适配

    2014-09-26 10:18:17
    自从苹果出了大屏iPhone后,iOS开发也要做适配了,想必Android程序员正在偷着乐呢;) 这里大概总结下这几天了解到的大屏适配的注意事项。   启用高分辨率模式 从Xcode6 GM版本开始,模拟器新增了iPhone6和...
  • 苹果在今年的 WWDC 上,正式公布了 iOS 10、macOS High Sierra 以及 watchOS 4 等操作系统。这次 WWDC 也是猛料最多的一次,除了全新 iMac Pro 外,苹果还发布了 HomePod 智能扬声器等新产品。iOS 11 对苹果来说至关...
  • ios9和ios10的新特性

    2019-09-27 00:25:46
    ios9和ios10的新特性 昨天面试了一个做ios开发的公司,其中面试官问我最新的ios系统版本是多少,以及它的特性是什么?由于自己是初学者,所以对这些没有关注过。今天特地搜索了一下关于ios9和ios10的新...
  • 切入维度与关注点 一、系统兼容 1.1 新增功能: 发布每个大系统,除了界面更新外,还会伴随着一些全新的功能,e.g. iOS8带来的widget....新系统发布后,iOS产品的开发工具Xcode也会进行更新,提供新
  • iOS小问题总结

    2017-11-10 08:24:53
    关键时刻,第一时间送达! ...好久没更新了,今天写一点平时...1.iOS11数字精度问题 /*!  @brief 修正浮点型精度丢失  @param str 传入接口取到的数据  @return 修正精度后的数据  */ +(NSStrin
  • 经过长达 3 个月多月的测试,iOS 11 正式版终于发布了。与前几代的 iOS 系统相比,iOS 11 是非常特别的存在,它是历史上测试版本最多的系统,经历了 10 个 Beta 测试版。iOS 11 不仅为 iPhone 带来了众多功能,还...
  • 1. iOS 应用创建 ( 1 ) 创建应用 ( 2 ) 运行应用 ( 3 ) iPhone 模拟器控制 2. iOS 设计界面 storyboard ( 1 ) LaunchScreen.storyboard 应用欢迎界面 ( 2 ) Main.storyboard 界面 ( 3 ) Main.storyboard 界面...
  • ,iosUI组件介绍,iOS开发常用工具整理,ios开发总结 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SDWebImage多个缩略图缓存组件 UICKeyChainStore存放用户账号密码组件 ...
  • iOS常用控件尺寸

    2019-09-05 11:34:27
    iOS 开发中用到的单位 pt 是独立像素的意思,它是绝对长度,不随屏幕像素密度变化而变化(和我们日常用到的毫米、厘米是一个意思,只是它要小得多),在非视网膜的 iPhone 上(iPhone 3G),苹果规定 1px=1pt,也...
  • UI 下拉刷新 EGOTableViewPullRefresh- 最早的下拉刷新控件。 SVPullToRefresh- 下拉刷新控件。 MJRefresh- 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能。...
  • 下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件。SVPullToRefresh - 下拉刷新控件。MJRefresh - 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能。...
  • iOS 常用第三方库

    2018-06-04 15:38:52
    转载自:https ://github.com/Tim9Liu9/TimLiu-iOS目录UI下拉刷新模糊效果自动版式富文本图表表相关与的TabBar隐藏与显示HUD与吐司对话框其他UI动画侧滑与右滑返回手势GIF动画其他动画网络相关网络连接图像获取网络...
  • IOS 屏幕适配(三)代码实现篇
1 2 3 4 5 ... 13
收藏数 253
精华内容 101