2017年6月计划

读书

  • 腾讯传
  • 零售的哲学
  • 区块链:定义未来金融与经济新格局

健身

  • 一周跑步5次每次5km以上
  • 每天50个俯卧撑
  • 每天50个仰卧起坐
  • 每天20个健腹轮

英语

  • 学习完成朱伟的练恋有词(串讲部分)
  • 每天听懂一篇VOA常速英语

2016年最后一个月

11月最后一周有点被,出力不讨好,吃一见长一智

12月需要调整

  • 坚持跑步,每周跑步5次
  • 坚持看书,一周读一本书
  • 本月坚持学习ios,恢复到去年的水平
  • 本月分享2次

Xcode 7中http通信错误

  • 错误:
    Xcode 7中http通信出现如下错误:Application Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

  • 原因:在iOS9中,苹果将原http协议改成了https协议,使用 TLS1.2 SSL加密请求数据

  • 解决方法 编辑 info.plist,加入如下设置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      <plist>
    <dict>
    ....
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>
    </dict>
    </plist>

assign、retain、copy举例解释

NSString *pt = [[NSString alloc] initWithString:@”abc”];

上面一段代码会执行以下两个动作

  1. 在堆上分配一段内存用来存储@”abc” 比如:内存地址为:0x1111 内容为 “abc”
  2. 在栈上分配一段内存用来存储pt 比如:地址为:0xAAAA 内容自然为0x1111

下面分别看下assign retain copy

1
2
3
assign的情况:NSString *newPt = [pt assing];   
此时newPt和pt完全相同 地址都是0xAAAA内容为0x1111即newPt只是pt的别名,
对任何一个操作就等于对另一个操作。 因此retainCount不需要增加。
1
2
3
retain的情况:NSString *newPt = [pt retain];   
此时newPt的地址不再为0xAAAA,可能为0xAABB 但是内容依然为0x1111。
因此newPt 和 pt 都可以管理"abc"所在的内存。因此 retainCount需要增加1
1
2
3
copy的情况:NSString *newPt = [pt copy]; 
此时会在堆上重新开辟一段内存存放@"abc" 比如0x1122 内容为@"abc
同时会在栈上为newPt分配空间 比如地址:0xAACC 内容为0x1122 因此retainCount增加1供newPt来管理0x1122这段内存

nonatomic

禁止多线程,变量保护,提高性能

1
2
3
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,
造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,
如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。

1
2
3
4
指出访问器不是原子操作,而默认地,访问器是原子操作。这也就是说,在多线程环境下,解析的访问器提供一个对属性的安全访问,
从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。
如果你不指定 nonatomic,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,
如果指定了nonatomic,那么访问器只是简单地返回这个值

iOS程序启动原理

UIApplicationMain

main函数中执行了一个UIApplicationMain这个函数

1
2
int UIApplicationMain(int argc, char *argv[], NSString *principalClassName,
NSString *delegateClassName);

  • argc、argv:直接传递给UIApplicationMain进行相关处理即可

  • principalClassName:指定应用程序类名(app的象征),该类必须是UIApplication(或子类)。如果为nil,则用UIApplication类作为默认值

  • delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议

  • UIApplicationMain函数会根据principalClassName创建UIApplication对象,根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性

接着会建立应用程序的Main Runloop(事件循环),进行事件的处理(首先会在程序完毕后调用delegate对象的application:didFinishLaunchingWithOptions:方法)
程序正常退出时UIApplicationMain函数才返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import <UIKit/UIKit.h>

#import "YYAppDelegate.h"

int main(int argc, char * argv[])
{
@autoreleasepool {

/*
argc: 系统或者用户传入的参数个数
argv: 系统或者用户传入的实际参数
1.根据传入的第三个参数创建UIApplication对象
2.根据传入的第四个产生创建UIApplication对象的代理
3.设置刚刚创建出来的代理对象为UIApplication的代理
4.开启一个事件循环(可以理解为里面是一个死循环)这个时间循环是一个队列(先进先出)先添加进去的先处理
*/
return UIApplicationMain(argc, argv, @"UIApplication", @"YYAppDelegate");
}
}

ios程序启动原理
ios程序启动原理

程序启动的完整过程

main函数

….

UIApplicationMain

  • 创建UIApplication对象

  • 创建UIApplication的delegate对象

delegate对象开始处理(监听)系统事件(没有storyboard)

  • 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
  • 在application:didFinishLaunchingWithOptions:中创建UIWindow
  • 创建和设置UIWindow的rootViewController
  • 显示窗口

根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)

  • 创建UIWindow
  • 创建和设置UIWindow的rootViewController
  • 显示窗口