引用:http://log.fyscu.com/index.php/archives/28/
文件格式
m3u文件是用来描述一个或多个媒体文件地址的纯文本文件,通常以 M3U 或 m3u 作为扩展名。
m3u文件里描述的最小单位(元素/行/记录),可以是一下三者之一:
1.一个文件的绝对路径
2.相对于m3u文件的相对路径
3.一个网络url
引用:http://log.fyscu.com/index.php/archives/28/
文件格式
m3u文件是用来描述一个或多个媒体文件地址的纯文本文件,通常以 M3U 或 m3u 作为扩展名。
m3u文件里描述的最小单位(元素/行/记录),可以是一下三者之一:
1.一个文件的绝对路径
2.相对于m3u文件的相对路径
3.一个网络url
关于直播,这里先推荐几篇相关的文字,都是非常经典的,虽然有些难,直播本来就很难,不难还叫直播吗?是吧!
本文要做的就是简单的分析 iOS 开发中常见的几种锁如何实现,以及优缺点是什么,为什么会有性能上的差距,最终会简单的介绍锁的底层实现原理。水平有限,如果不慎有误,欢迎交流指正。同时建议读者在阅读本文以前,对 OC 中各种锁的使用方法先有大概的认识。
在 ibireme 的 不再安全的 OSSpinLock 一文中,有一张图片简单的比较了各种锁的加解锁性能:
前段时间看了几个开源项目,发现他们保持线程同步的方式各不相同,有@synchronized、NSLock、dispatch_semaphore、NSCondition、pthread_mutex、OSSpinLock。后来网上查了一下,发现他们的实现机制各不相同,性能也各不一样。不好意思,我们平常使用最多的@synchronized是性能最差的。下面我们先分别介绍每个加锁方式的使用,在使用一个案例来对他们进行性能对比。
本文摘自:伯乐在线,因为自己研究并学习ios设计模式的时候寻找了好多相关文章,最后发现这篇才是最适合ios开发的,当然你也可以自己通过C或者java设计模式的规范进行演变。
源码下载地址:https://github.com/al1020119/iCocosDesignPattern
使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象。
NSArray *array = [[NSArray alloc] initWithObjects:@1, nil];
NSArray *array2 = array.copy;
array 就是原型了,array2 以 array 为原型,通过 copy 操作创建了 array2。
当创建的实例非常复杂且耗时,或者新实例和已存在的实例值相同,使用原型模式去复制已经存在的实例效率更高。
定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得类的实例化延迟到其子类。
工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂类来创建不同的产品实例。
工厂方法模式的扩展性也很好,新增的产品类并不需要修改客户端代码。但每新加一个产品类都需要新建一个工厂类,会造成项目中的类过多。
而在 Cocoa Touch 框架中,以 NSNumber 举例,将原有的 alloc+init 拆开写:
id obj1 = [NSNumber alloc];
id obj2 = [NSNumber alloc];
id obj3 = [obj1 initWithBool:YES];
发现 + alloc 后并非生成了我们期望的类实例,而是一个NSPlacehodlerNumber 的中间对象,后面的 – initWithXXXXX 消息都是发送给这个中间对象,再由它做工厂,生成真的对象。如 obj3 的实际类型为 NSCFBoolean,而 obj4 的实际类型为 NSCFNumber 。
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
在 Cocoa Touch 框架中,类簇是抽象工厂模式在 iOS 下的一种实现,以 NSArray 举例,将原有的 alloc+init 拆开写:
id obj1 = [NSArray alloc]; // __NSPlacehodlerArray *
id obj2 = [NSMutableArray alloc]; // __NSPlacehodlerArray *
id obj3 = [obj1 init]; // __NSArrayI *
id obj4 = [obj2 init]; // __NSArrayM *
发现 + alloc 后并非生成了我们期望的类实例,而是一个NSPlacehodlerArray 的中间对象,后面的 – init 或 – initWithXXXXX 消息都是发送给这个中间对象,再由它做工厂,生成真的对象。这里的 NSArrayI 和 __NSArrayM 分别对应 Immutable 和 Mutable(后面的 I 和 M 的意思)
于是顺着思路猜实现,__NSPlacehodlerArray 必定用某种方式存储了它是由谁 alloc 出来的这个信息,才能在 init 的时候知道要创建的是可变数组还是不可变数组。
抽象工厂将一系列的产品族统一到一起创建,增加产品族很方便,但增加产品很麻烦,需要改动太多的类的接口。
将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。 生成器可以将构建对象的过程分为,客户 – 指导者 – 生成器 的关系,
CharacterBuilder *characterBuilder = [[StandarCharacterBuilder alloc] init];
ChasingGame *game = [[ChasingGame alloc] init];
Character *player = [chasingGame createPlayer:characterBuilder];
Character *enemy = [chasingGame createEnemy:characterBuilder];
characterBuilder 就是生成器了,而 game 就是指导者。指导者里声明了创建不同表现的对象的方法。而方法里由生成器 characterBuilder 来构建不同的 Character 类型的对象。
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
在 Cocoa Touch 框架中,最常见的使用了单例模式的就是 UIApplication 类了。每个应用程序有且仅有一个 UIApplication 的实例,它由 UIApplicationMain 函数在程序启动时创建为单例对象,之后,对同一 UIApplication 实例可以通过其 sharedApplication 类方法进行访问。
单例用来集中管理对类的对象所提供的资源,例如应用程序中需要用集中式的类来协调其服务,这个类就应该生成单一的实例。
将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适配器模式分为类适配器模式和对象适配器模式。
类适配器模式中适配器和被适配者是继承关系。request 方法里会去调用 super 的 specificRequest 方法,达到将类的接口转换成客户希望的另一个接口。
适配器模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
桥接模式是软件设计模式中最复杂的模式之一,在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化。
桥接模式可以让抽象与实现之间不形成绑定关系,在运行时可以切换实现,也将抽象和实现完全解耦,可以独立扩展。
为系统中的一组接口提供一个统一的接口。外观顶一个高层接口,让子系统更易于使用。
外观模式主要是使用一个外观类,为复杂的子系统提供一个简单的接口,而子系统的复杂调用交给外观类去做。
用一个对象来封装一系列对象的交互方式,中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
我们开发的程序是由大量的类来组成的,随着程序功能的不断增加,类和类之间的依赖关系也跟着趋于复杂,而中介者模式便能解决这个问题,
UINavigationController 就是一个中介者,如下图所示
视图控制器的切换都是与 UINavigationController 做交互。由 UINavigationController 去做集中管理。
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
在 Cocoa Touch 框架中通知和 KVO 都实现了观察者模式。通知是由一个中心对象为所有观察者提供变更通知,KVO 是被观察的对象直接向观察者发送通知。
被观察者不需要知道有多少个观察者和观察者的更新细节,降低被观察者和观察者之间的耦合。
将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。
在 Cocoa Touch 框架中,UIView 被组织成一个组合结构。每个 UIView 都可以将其它 UIView 设置为自己的子视图,形成一个树形结构,让客户端可以对单个 UIView 或者对 UIView 组合统一对待。
既平移一个 UIView,可以做到平移这一个 UIView 组合,且操作方法与平移单个 UIView 一致。
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示,
在 Cocoa Touch 中的 NSEnumerator 就实现了迭代器模式,如以下代码
NSArray *anArray = @[@"this", @"is", @"a", @"test"];
NSEnumerator *itemEnumerator = [anArray objectEnumerator];
NSString *item;
while (item = [itemEnumerator nextObject]) {
NSLog(@"%@", item);
}
迭代器分为两种,上面使用了一个外部迭代器,外部迭代器让客户端直接操作迭代过程,如上面代码就是使用一个 while 循环去迭代。
下面是使用了内部迭代器,客户端不需要知道实现迭代的方式。
NSArray *anArray = @[@"this", @"is", @"a", @"test"];
NSString *string = @"a";
[anArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@", obj);
if ([obj isEqualToString:string]) {
*stop = YES;
}
}];
客户端不需要手动实现迭代器,只要对每个元素进行处理就行。
表示一个作用于某对象结构中的各元素的操作,它让我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
当一个复杂的对象结构包含很多其他的对象,每个对象都有不同的接口,这个时候如果想添加新的接口进行新的操作,就得修改该对象的类,如果每个对象都需要添加新操作,就需要修改更多的类。而访问者模式就是用来不修改原有类添加新的操作。
访问者模式涉及两个关键元素,访问者和被访问对象。访问者遵从访问协议,访问协议里声明了访问方法。访问方法类似下面
- (void)visitEngine:(NimoEngine *)engine;
- (void)visitWheel:(NimoWheel *)wheel;
访问者模式流程,直接调用访问者里的访问方法,访问方法里实现了新添加的操作,engine 与 wheel 既被访问对象,达到了将新操作集中在访问者里处理的效果。如果再需要新添加一系列对各个元素的操作,只需要再添加一个访问者类就行。
访问者能访问复杂元素里的每一个元素,然后由访问者对这些元素进行行为扩展。
装饰(Decorator)
动态地给一个对象添加一些额外的职责。就扩展功能来说,装饰模式相比生成子类更为灵活。
Category 就是实现了装饰的设计模式。Category 是 Objective-C 的语言功能,通过它可以给类添加方法的接口与实现,而不必子类化。 从这个设计模式的描述联想到 Category,就没什么难理解了。 责任链(Chain of Responsibility)
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间发生耦合。此模式将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
Cocoa Touch 中的事件处理流程–响应者链就实现了责任链模式。以点击为例,首先通过 hit-test view 的流程找到被点击的视图,被点击的视图如果不处理点击事件,则沿着响应者链向上回溯,比如给父视图发消息,让父视图去处理,父视图不处理则继续沿着响应者链向上回溯,直到有对象处理它为止,如果都不处理,则该事件丢弃。
定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使子类可以重定义算法的某些特定步骤而不改变该算法的结构。
模板方法可以提高可扩展性与可复用性,比如 UIView 类中的定制绘图,UIView 的结构不改变,只是继承 UIView,再重载 – (void)drawRect:(CGRect)rect 方法。所以 – (void)drawRect:(CGRect)rect 就是模板方法,默认什么都不做或者只是做了部分操作,缺少特性操作,用来给子类选择重载与实现的方法。
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
举一个常见的例子,验证 UITextField 输入是否有效。有两个算法分别是验证邮箱的和验证电话号码的。可以通过 if else 这样的判断代码来决定执行哪个算法。也可以通过策略模式,将算法封装起来,如下图 
Strategy 是这一系列算法的父类,ConcreteStrategyA, B, C。是三种算法,给 Context 对象添加一个 Strategy 类型的属性,里面存放着 ConcreteStrategyA 或者 B,C。然后 Context 对象就知道去执行哪个算法。也就知道自己需要执行什么策略。
策略模式首先将算法都封装起来了,易于理解,且易于切换和扩展。
命令(Command)
将请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
Cocoa Touch 框架中的 NSInvocation 就是实现了命令模式。
NSMethodSignature*signature = [ViewController instanceMethodSignatureForSelector:@selector(sendMessageWithNumber:WithContent:)];
//1、创建NSInvocation对象
NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
//invocation中的方法必须和签名中的方法一致。
invocation.selector = @selector(sendMessageWithNumber:WithContent:);
/*第一个参数:需要给指定方法传递的值
第一个参数需要接收一个指针,也就是传递值的时候需要传递地址*/
//第二个参数:需要给指定方法的第几个参数传值
NSString*number = @"1111";
//注意:设置参数的索引时不能从0开始,因为0已经被self占用,1已经被_cmd占用
[invocation setArgument:&number atIndex:2];
NSString*number2 = @"啊啊啊";
[invocation setArgument:&number2 atIndex:3];
//2、调用NSInvocation对象的invoke方法
//只要调用invocation的invoke方法,就代表需要执行NSInvocation对象中制定对象的指定方法,并且传递指定的参数
[invocation invoke];
将行为封装成对象,而不是直接触发行为,因为是对象,所以可以很容易的设计一个命令队列,也可以方便的记录进日志里,以及实现行为的撤销。(因为行为对象可以记录进日志里,所以可以根据日志得知上一个操作做了什么,从而进行撤销)。
利用共享技术有效地支持大量细粒度的对象。
tableViewCell 的重用机制就是实现了享元模式。在要使用一个 Cell 的时候,会先去重用池里看看 tableView 有没有可以重用的 cell,如果有重用该 cell,没有创建一个,这就是享元模式。
享元模式主要有两个关键组件,可共享的享元对象和保存它们的享元池。
举另一个实现例子,画面上需要显示 100 个相同的图案,可以只生成一个包含该图案 image 的 imageView。其它 99 个只需要去享元池里去拿这个 imageView 实例的信息,然后在页面里直接绘制图案,这样就不需要生成 100 个图案实例。
享元模式通过共享一部分必须的对象,减少对象的创建,节省大量的内存。
为其它对象提供一种代理以控制对这个对象的访问。
代理设计模式的英文名是 Proxy pattern,和我们常见的 delegate(委托) 没关系。
iOS 中常见的代理模式例子为引用计数,当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少内存用量。典型做法是创建一个复杂对象及多个代理者,每个代理者会引用到原本的复杂对象。而作用在代理者的运算会转送到原本对象。一旦所有的代理者都不存在时,复杂对象会被移除。
当然,上面的代理模式中的代理者什么都没做,代理对象作为 A 和 C 中间的协调者,可以多做点操作,可以理解为 VPN 中的代理者可以对传输数据加密,而 A 和 C 中的代理者,也可以隐藏 C 的信息,做到对 C 的保护。
在不破坏封装的情况下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
Cocoa Touch 框架中归档可以实现备忘录模式,Cocoa 的归档是对对象及其属性还有同其他对象间的关系进行编码,形成一个文档,该文档可以保存于文件系统,也可在进程或网络间传输,最后又可以通过解档将文档解码成与该对象归档时状态一致的对象。
既将对象保存一个备份放置到其它地方,可以随时使用备份将该对象恢复到原先保存的状态,用来储存关键对象的关键状态。
clpaial10201119(Q Q:2211523682)
http://weibo.com/u/3288975567?is_hot=1
栈是只能在一端进行插入和删除的线性表。 (别看只是个定义,非常重要,已经道出了运算方法:只能在一端插入和删除。)
栈的特征:后进先出,先进后出。
插入和删除元素的一端称为栈顶。(说明了我们在栈顶操作) 另一端称为栈底。 插入元素和删除元素的操作称为入栈和出栈。
冒泡排序(交换)
快速排序(交换)
基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。 算法的实现:
void bubbleSort(int a[], int n){
for(int i =0 ; i< n-1; ++i) {
for(int j = 0; j < n-i-1; ++j) {
if(a[j] > a[j+1])
{
int tmp = a[j] ; a[j] = a[j+1] ; a[j+1] = tmp;
}
}
}
}
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
阅读目录
1、顺序查找
2、二分查找
3、插值查找
4、斐波那契查找
5、树表查找
6、分块查找
7、哈希查找
查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算,例如编译程序中符号表的查找。
把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并
排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……
思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之
分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法
这自然导致递归过程的产生。分治与递归像一对孪生兄弟