PART3

来源:互联网 发布:人人商城 源码 编辑:程序博客网 时间:2024/05/21 15:01

验证O(f(N))的一个常用技巧)

方法是在《数据结构与算法C++描述第三版》中学习到的,这里记录一下,方便后面的查阅。

T(N)是凭借经验在运行程序时实际观察到的时间,f(N)是通过理论计算的出一个函数关系式。

在N的某个范围内计算T(N) / f(N) = k(范围的不断增加通常以2的倍数隔开,如N = 2、4、6、8……)。

如果k收敛于一个正常数,表明运行时间与f(N)理想近似;如果k收敛于0,说明f(N)估计过大,T(N) = O(f(N));如果k是发散的,没有任何规律,则表示f(N)估计过低,T(N)≠O(f(N))。

例如:T(N) = 1000N, f(N) = N ^ 2,k = 1000 / N。当N = 1000,T(N) = f(N)。当N > 1000时,k -> 0,T(N) = O(f(N)),这与大O记法的定义相吻合,即存在正常数N0和c使得当N ≥ N0,有T(N) ≤ cf(N)。在这里c = 1, N0 = 1000。

UIView的autoresizingMask属性

在Apple提出自动布局和Size Class之前,屏幕适配的工作是通过autoresizingMask这个属性来完成的,因为之前的iPhone的屏幕尺寸只有一种,做好屏幕旋转的布局调整大体就能满足需求了,况且并不是所有的App都有旋转屏幕的必要。它是UIViewAutoresizing类型的枚举变量,取值如下:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {    UIViewAutoresizingNone                 = 0,    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,    UIViewAutoresizingFlexibleWidth        = 1 << 1,    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,    UIViewAutoresizingFlexibleHeight       = 1 << 4,    UIViewAutoresizingFlexibleBottomMargin = 1 << 5};

枚举值的意思表征地很明显,第二个表示调整视图与父视图的左边间距确保视图右边间距不变。如果左右同时可调整,则说明左右两边保持间距比例不变,此时视图相对于父视图就是水平居中。同理可以以此实现上下居中,两相结合就是居中显示。这个属性生效的前提是俯视图的autoresizesSubviews属性设置为YES,默认值是YES。

更详尽的资料:自动布局之autoresizingMask使用详解(Storyboard&Code)

UIWindow的windowLevel属性

windowLevelUIWindowLevel类型,其实就是CGFloat的又一个别名。同时UIKit还定义了三个常变量来为其赋值,分别为UIWindowLevelNormal(0.0f,默认值)UIWindowLevelAlert(2000.0f)UIWindowLevelStatusBar(1000.0f)UIWindow实例的显示与这个属性值有关,值越大,显示在越前面(指的是越靠近用户所见),与调用makeKeyAndVisible这个方法的顺序无关。

另外,当等级相同时,只有前一个UIWindow实例会被显示出来

闰年的计算

看到这个标题,你可能觉得笔者在偷懒,这个小case还单独列出来。但是笔者想说的是“好记性不如烂笔头”,在这里贴出是为了方便查阅,相信各位也是记不了多久的,毕竟这个问题在实际应用场景中很少出现。

相信很多人都被小学老师坑过,说:只要年份能整除4,则该年就是闰年,然事实却并非如此。这里只是给出一个条件判别式子,其中的原因,有兴趣的朋友可以了解了解!

if (year % 4  == 0 && year % 100 != 0  || year % 400 == 0) 

OC中字符串判等问题

不说废话,直接上代码:

NSString *str1 = @"test";NSString *str2 = @"test";        if (str1 == str2) {            NSLog(@"str1 = str2");        } else {            NSLog(@"str1 != str2");        }

如果是下面这句判等语句,你肯定不会有任何怀疑就说出了正确的答案!

if ([str1 isEqualToString:str2]) {         //......   }

然而在这里想说的是最上面的判断条件结果也是真!我们不妨先来看看它们的地址:

// (当然实际具体的地址是系统分配的,将会不断变动,但是不变的是str1、str2地址相同这一事实!)//str1:0x100001040//str2:0x100001040

就算我们将它们放置于不同的方法中,结果别无二致。如果我们向下面这样处理一下的话,结果就会发生变化:

[[NSUserDefaults standardUserDefaults] setObject:@"test" forKey:@"testString"];NSString *str2 = [[NSUserDefaults standardUserDefaults] objectForKey:@"testString"];NSLog(@"str2:%p", str2);

也就是说str1和str2的地址将不再相同,这是怎么一回事了?

我们知道堆栈的概念(这里有一篇文章可以看看),也知道栈区时候系统管理的,堆区的使用则需要程序员自己手动申请。而对于临时变量,系统会在栈区开辟空间来临时存储它们的值,而对于对象这类的实例则存储在堆区,这就是为什么不合理使用递归会报stack overflow(栈溢出)错误(创建临时的局部变量太多,而每个程序所享有的栈空间是有限的)。

Objc中,字符串实例实际上也是对象,这就不难理解它是存放在堆区了,更确切地说是堆区里的字符常量区。一个简单的新建字符串变量及其赋值就可以用下面这张图表示:

这里写图片描述

对于字符常量区的数据其实是相互共享的,也就是说如果字符串变量的值相同,那么它们真正访问的是同一个地址的内容,这也就解释了上面出现相等的原因,这里我们也可以推测当我们打印字符串地址时,实际上打印出的是内容的地址,因为栈区的临时变量地址对我们来说是毫无意义的。而通过数据持久化方式存储的内容,它们就被固化下来了,因为堆区里面的内容会随着程序的运行不断被清理,故而地址将不再相等。这也就是为什么我们平常使用isEqualToString来判断字符串是否相等的原因,也就是纯粹比较内容是否相等。

0 0
原创粉丝点击