首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

《企业级ios应用开发实战》一3.5 块编程

3.5 块编程 C语言的运行时特性中包括了块,标准C工作组的 N1370: Apple’s Extensions to C 中(其中也包括垃圾回收)对块进行了定义。作为C语言的扩展,Objective-C在OSX 10.6及iOS 4.0以后支持块语法。块运行时也会被集成到LLVM的compiler-rt子项目存储库中。 3.5.1 块的特点 一些面向对象的动态语言如ruby、groovy,都提供了对块的支持(在groovy中,块被称作为闭包“closure”)。块是用一对{}括号括起来的多个语句的集合。类似于函数,但不同于函数,可以把块作为表达式或变量的一部分,或者作为参数传递。在作为参数传递块时,代码被作为数据的一部分进行传递。块具有以下特征:同函数一样,有类型化参数列表。有返回结果或者要申明返回类型。能获取同一作用域(与块所在同一作用域)内的状态。可以修改同一作用域的状态(变量)。与同一范围内的其他块同享变量。在作用域释放后能继续共享和改变同一范围内的变量。除以上特点外,甚至可以复制块并传递到其他后续执行的线程,编译器和运行时负责把所有块引用的变量保护在所有块的拷贝的生命周期内。当然,这已经超出了本章的范围,可以参考苹果官方文档来了解这些内容。 3.5.2 Objective-C 中的块 对于C和C++,块是变量,但对于Objective-C,块仍然是对象。下面简单介绍Objective-C中的块。1.块变量声明用^操作符声明一个块变量的开始,分号表示块结束,如下代码所示: int multiplier = 7; int (^myBlock)(int) = ^(int num) { return num multiplier; }; 块语法比较奇怪,块变量声明的解释如图3-2所示。 块变量的声明语句从前至后分为了几部分:返回值类型,如int、double,如果未显式地声明块的返回值类型,可能会自动从块代码中推断返回类型(通过return语句)。块变量名用括号括住,块变量名前加^符号。参数类型用括号括住,多个参数以逗号分隔,如果参数列表为void,而且返回类型依靠推断,可以省略参数列表的void。等号,将后面的块赋值给前面的块变量(即myBlock)。以^开头并以;结束的块定义。块定义中又分为以下两个部分(除去开头的^和结尾的;外):参数列表,同函数的参数列表。块体,同函数体。值得注意的是,块可以使用同一作用域内定义的变量,而函数不行。一旦声明了块,你可以像使用函数一样调用它: int multiplier = 7; int (^myBlock)(int) = ^(int num) { return num multiplier; }; printf ( "%d", myBlock(3)); 2.行内块有时候,你不准备重复使用某个块,因此你不必为它想一个名称。那你可以使用行内块而不用声明为块变量。以下代码来自苹果文档:// gsort_b类似标准的 gsort_r 函数,但它最后一个参数是一个块。 char myCharacters[3] = { "TomJohn", "George", "Charles Condomine" }; qsort_b(myCharacters, 3, sizeof(char ), ^(const void l, const void r) { char left = (char )l; char right = (char )r; return strncmp(left, right, 1); }); // myCharacters 现在是 { "Charles Condomine", "George", TomJohn" } 在qsort_b 方法调用中,第4个参数就是一个匿名的块(行内块)。匿名块跟块变量不同,它没有变量名,因此你无法重用匿名块。下次调用这个块时,必须把整个块定义的代码再复制一遍。3.__block关键字块允许访问本地变量。这很重要。它使得我们在线程间共享变量变得简单,而且,你可以规定一个本地变量是否可以写,这可通过使用__block关键字,这是一种类类似register、auto和static存储类型修饰符。用__block修饰的变量,可以在所有同一作用域内的块,以及块复制之间共享数据。在指定作用域内的多个块能同时使用共享变量。如同块,__block变量也使用栈存储。如果使用block_copy拷贝块(或者向块发送copy消息),变量被拷贝到堆里。而且,__block变量的地址随后就会改变。__block变量有两个限制:不能是可变长度的数组,也不能是包含C99可变长度数组的结构体。下面显示了__block变量的使用: __block int x = 123; // x 是块可写的 void (^printXAndY)(int) = ^(int y) { x = x + y; printf("%d %d\n", x, y); }; printXAndY(456); // 打印出: 579 456 // x 现在的值是:579 下面显示了在块中使用多种类型的变量: extern NSInteger CounterGlobal; static NSInteger CounterStatic; { NSInteger localCounter = 42; __block char localCharacter; void (^aBlock)(void) = ^(void) { ++CounterGlobal; ++CounterStatic; CounterGlobal = localCounter; localCharacter = 'a'; }; ++localCounter; localCharacter = 'b'; aBlock(); }

优秀的个人博客,低调大师

《企业级ios应用开发实战》一3.4 KVO模型

3.4 KVO模型 KVO(key-value observer,“键-值”观察)模型是Cocoa绑定技术中常用的一种编程模型,它可以使一个对象在属性值发生变化时主动通知另一个对象并触发相应的方法。与NSNotification 不同,KVO没有所谓的中心对象来为所有观察者提供变化通知。当“被观察者”对象状态发生变化时,通知被直接发送至“观察者”对象,如图3-1所示。 在图3-1中,观察者是aButton,被观察者是modelObject。aButton是一个按钮控件,它是一个UI对象,有一个BOOL型的enabled属性,表示按钮是否可被点击。modelObject对象是一个模型对象,它没有可以呈现给用户的界面,同样,它有一个BOOL属性selected。通过KVO模型,modelObject的selected属性可以绑定到UIButton的enabled属性。即当modelObject的selected属性发生变化时(这是可以被编程的),KVO会主动通知aButton这种改变,因此按钮的外观随之可发生相应的呈现。比如由不可点击的灰色改变为可点击的着色状态。KVO是一种很有用的绑定技术(Cocoa还提供另外一种绑定技术:Dynamic bingding)。而且它是由被观察的对象主动通知观察者的,并不需要经过一个统一的通知中心(如后面章节介绍的通知技术所述),它的执行效率和适用场景要更佳。为了实现KVO,你需要进行如下操作:注册观察者。所谓观察者即对象状态变化时需要通知的对象。接收变更通知。接收变更通知主要是让观察者实现指定方法,在指定方法中,你可以接收到对象状态变更的消息,并在方法中进行处理。取消所注册的观察者。观察者处理完状态变更消息之后,需要取消原先的注册状态。 3.4.1 注册KVO 对象要将自己注册为观察者,必须发送一个addObserver:forKeyPath:options:context:消息至被观察对象: [account addObserver:inspector forKeyPath:@"name" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; 以上例子将inspector对象注册为account对象的观察者,并表明观察者将对名为“name” 的属性变更感兴趣。forKeyPath参数“name”注明了需要观察的属性的关键路径KeyPath。关键路径KeyPath实际是一个字符串,用于表示某个属性,你可以直接用属性名。但如果某属性是一个对象,则KeyPath可以用“.”语法的形式表示对象成员,如“account.name”。options参数注明了对该属性的何种状态感兴趣。NSKeyValueObservingOptionNew表示属性在变更后的新值,NSKeyValueObservingOptionOld表示属性未改变之前的值。以上例子中的option参数设置表明,当name属性变更时,会将这两个值以NSDictionary的方式(即change参数)提交给观察者,观察者可以从NSDictionary中以键-值对的方式检索到这两个值。context参数用于传递一个对象,该对象(或指针)会在属性变化时通过变更通知传递给观察者(通过context参数)。移除观察者的注册,使用方法removeObserver forKeyPath: [subject removeObserver:observer forKeyPath:@"name"]; 3.4.2 接收变更通知 观察者要想收到对象的属性变更通知,需要实现方法observeValueForKeyPath:ofObject: change:context:,并在其中进行通知的处理。例如: - (void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void )context { NSLog(@"%@",keyPath); if ([keyPath isEqual:@"name"]) { NSLog(@"name is changed:%@", [change objectForKey:NSKeyValueChangeNewKey]); }else [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } 3.4.3 发送变更通知 NSObject支持两种属性变更通知,一种是自动变更通知,一种是手动变更通知。一般情况下,使用自动变更通知则更为简单,因此我们主要介绍自动变更通知。1.自动变更通知要使用自动变更通知,需要实现被观察者的 automaticallyNotifiesObserversForKey方法,在此方法中明确说明需要使用自动变更通知的属性。对于需要使用自动变更通知的属性,返回YES,如下代码所示: + (BOOL) automaticallyNotifiesObserversForKey:(NSString)key { // 对于属性name ,使用自动通知 if ([key isEqualToString:@"name"]) { return YES; } // 确保调用了父类的automaticallyNotfiesObserversForKey方法 return [super automaticallyNotifiesObserversForKey:key]; } 然后,在name属性发生变化的时候通知观察者,比如调用以下语句之一: subject.name=newName; [subject setValue:newName forKey:@"name"]; [subject setValue:newName forKeyPath:@"name"]; 如果属性是集合类型,则可以使用方法mutableSetValueForKey来支持以下集合方法导致的自动变更通知:添加:insertObject:InKey:或者insertObject:AtIndex:替换:replaceObject:InKey:或者replaceObject:AtIndex:删除:removeObjectFromKey:或者removeObjectAtIndex:2.手动变更通知对于手动变更通知,除了需要在automaticallyNotifiesObserversForKey:方法中将要使用的手动变更通知返回NO外,还需要 在改变值之前调用willChangeValueForKey:并在更改它之后调用didChangeValueForKey:。为了便于你理解KVO模型,我做了一个示例程序,放在光盘“source/第3章/TestKVO”文件夹,它使用了本节所介绍的知识点,可供参考和学习。

优秀的个人博客,低调大师

《企业级ios应用开发实战》一3.6 可变参数

3.6 可变参数 我们知道,C和C++语言支持可变参数的函数,例如我们常用的NSLog和printf函数。Objective-C作为C语言的超集,当然毫无例外地也支持可变参数。迄今为止,我们至少用过了一种使用可变参数的方法,即NSString的stringWithFormat:方法。C语言通过stdarg.h库支持可变参数,Objective-C 也不例外。在C语言中,如果你要使用可变参数,必须包含头文件stdarg.h,但在Cocoa中却不必,因为苹果已经在 NSObjC Runtime.h中包含了stdarg.h。stdarg.h的定义如下: typedef __void va_list; #define va_start(ap, param) __builtin_va_start(ap, param) #define va_end(ap) __builtin_va_end(ap) #define va_arg(ap, type) __builtin_va_arg(ap, type) 首先定义了一个va_list类型,其实就是一个void,即可以指向任何类型的指针。你可以把它看成是char,因为char*实际上也可以指向任何内存单元的地址。然后是3个预定义宏,va_start、va_end和va_arg。可以看出stdarg.h完全是以“预定义宏”这种“古老”的方式来支持可变参数的。接下来我们看一个例子,该方法使用了一个可变参数,并将这些可变参数进行了累加,然后返回一个NSNumber: - (NSNumber ) addValues:(int) count, ... { va_list args; va_start(args, count); NSNumber value; double retval; for( int i = 0; i < count; i++ ) { value = va_arg(args, NSNumber ); retval += [value doubleValue]; } va_end(args); return [NSNumber numberWithDouble:retval]; } 代码说明:第1行是方法定义,该定义应当加到头文件中。省略号...表明方法接收一系列数目不定的参数,在...前面至少需要指定一个任意类型的参数。有时我们必须知道参数的个数以防止出现无效的引用,但在某种情况下,参数个数是可以通过其他参数推断出来的(例如NSLog或printf函数可以通过计算%号的个数推断可变参数的个数),或者对于NSMutableArray来说,它总是以nil终止。如果是最后一种方法,我们可以把方法重新定义为: - (NSNumber ) addValues:(NSNumber ) firstNumber, ... 这样,我们就可以用以下调用方式代替“addValues:3,num1,num2,num3”: addValues:num1,num2,num3; 这样,我们就可以省略第1个表示可变参数个数的int参数。第2行中的va_list是void *类型,因此它实际上是一个可变的对象数组。第3行用args来存放可变参数列表,而count则表示函数最后一个参数(即第一个“固定参数”)。这将使编译器把args指向第1个参数后的位置(通过count地址加上count变量的长度)。很奇怪吗?可变参数中第1个参数的位址为什么是“count地址+count的长度”?因为对于大多数C编译器,函数栈中参数的存放顺序是从右到左的,也就是说先放入可变参数的最后一个参数,再放可变参数的倒数第2个参数……,然后放可变参数的第1个参数,最后是固定参数count。而与此同时,栈的方向是向下的,即先入栈的数据位于高地址,后入栈的数据则位于栈的起始地址。这样,实际上最后放入的固定参数count的地址变成了栈的起始地址。而紧随count之后的地址则是可变参数的第1个参数地址,即“count地址+count的长度”,因此编译器要能找到第1个可变参数的地址,只要知道1个参数:count就够了,由count取得函数栈的起始地址,加上sizeof(count),得到第1个可变参数的地址。va_start的第1个参数args是一个输出参数,经过va_start调用之后,args将等于arg_start计算出来的第1个可变参数的地址。第6行是一个for循环,因为我们无法通过 args 自身推断 args 的大小,因此必须显式地用count来指定args的大小。或者可以使用nil终止的列表来检索可变参数。如果你使用nil终止的数组作为可变参数,则应该用下面一行来代替第6~7行: while( value = va_arg( args, NSNumber ) ) 第 7 行将 args 中的下一个参数放入 value,并显式地转为 NSNumber*(如果不知道类型,可以用id)。第10行表明,一旦使用完args列表,就关闭它 。提示:如果你使用va_arg(args,double)(或者float等其他原始类型),那么当你试图传递一系列整数作为参数时(例如:addValues:4,4,3,2,1),可能会出现一些古怪的结果。而如果你显式地将这些参数说明为double(例如,double num1,double num2,double num3,double num4)则不会有什么问题。这是因为,如果编译器看到一个方法有一个double参数但你却传递了一个整数给这个方法时,它会进行类型转换。但如果方法使用了可变参数,编译器无法知道参数所使用的类型,因此编译器只会简单地把参数作为整型处理。

优秀的个人博客,低调大师

《企业级ios应用开发实战》一3.7 本章小结

3.7 本章小结 Objective-C是C语言的扩展和超集。本章重点从C语言特性和面向对象特性两个方面对Objective-C的语言特性进行论述,包括基本语法(数据类型、常量/变量、分支与循环)、运行时特性(反射支持)和一些特有属性(NS类、类别和协议、消息、KVO和块)。通过这些介绍,我们对Objective-C的一些重要特性有了最基本的了解,从而为后续的学习打下坚实的基础。接下来,本书将陆续介绍iOS SDK中的一些重要框架,如UIKit、Core Animation、Quartz Core,以及其他一些第三方的开源框架。

优秀的个人博客,低调大师

《Android应用开发攻略》——2.6 在Android中创建闪屏

2.6 在Android中创建闪屏 Rachee Singh2.6.1 问题你打算创建应用程序加载时显示的闪屏(splash screen)。2.6.2 解决方案你可以采用活动或者对话框的形式构建闪屏。因为闪屏的目标在几秒钟之内就能完成,所以它可以在短时间或者单击闪屏上的一个按钮之后消失。2.6.3 讨论闪屏发明于PC时代,最初是在PC速度较慢的时候遮盖缓慢构建的GUI。供应商则将闪屏用于品牌宣传。但是在移动领域中,最长的应用程序启动时间可能少于1秒,人们开始认为闪屏已经不合时宜。在 eHealth Innovation中,我们对此进行了论证, BANT应用程序闪屏在1秒之后就消失。问题是:我们是否仍然需要闪屏?现在是否应该摒弃闪屏的概念?在大部分移动应用中,应用启动器中会显示名称和徽标,在其他许多屏幕中也会出现名称和徽标,是否应该

优秀的个人博客,低调大师

SpringBoot开发案例之整合定时任务(Scheduled)

来来来小伙伴们,基于上篇的邮件服务,定时任务就不单独分项目了,天然整合进了邮件服务中。 不知道,大家在工作之中,经常会用到那些定时任务去执行特定的业务,这里列举一下我在工作中曾经使用到的几种实现。 任务介绍 Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。Timer的优点在于简单易用;缺点是Timer的所有任务都是由同一个线程调度的,因此所有任务都是串行执行的。同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务,不过这种实现已经被项目所废弃。 开源集群任务框架Quartz,这是一个功能比较强大的的调度器,适合做任务集群,解决单点故障,目前项目中在使用。 Spring家族自带的Scheduled,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,适用于简单的任务,微服务使用很方便。 项目应用 创建任务 代码中,可以发现,sendMail方法上注解被注释掉了,目前我们采用的是xml配置实现的。 import org.springframework.stereotype.Component; /** * 统计失败邮件定时重新发送 * 创建者 科帮网 * 创建时间 2017年7月21日 * */ @Component("sendMail") public class SendMail { //@Scheduled(cron = "0/5 * * * * ?") public void sendMail() { System.out.println("统计失败邮件定时重新发送开始"); } } 配置文件 <!-- 配置任务线性池 --> <task:executor id="executor" pool-size="5" /> <task:scheduler id="scheduler" pool-size="5"/> <!-- 启用注解驱动的定时任务 --> <task:annotation-driven executor="executor" scheduler="scheduler" proxy-target-class="true"/> <task:scheduled-tasks scheduler="scheduler"> <!-- 统计失败邮件定时重新发送 --> <task:scheduled ref="sendMail" method="sendMail" cron="0/5 * * * * ?"/> </task:scheduled-tasks> 启动项目 /** * 启动类 * 创建者 科帮网 * 创建时间 2017年7月19日 * */ @EnableAutoConfiguration @ComponentScan(basePackages={"com.itstyle.main"}) @ImportResource({"classpath:spring-context-dubbo.xml","classpath:spring-context-task.xml"}) public class Application { private static final Logger logger = Logger.getLogger(Application.class); public static void main(String[] args) throws InterruptedException { SpringApplication.run(Application.class, args); logger.info("项目启动 "); } } 启动后,控制台会每5s打印"统计失败邮件定时重新发送开始"。当然Scheduled的功能不仅仅如此,我们查找源码Scheduled类,可以发现还有一些注解属性,这里就不一一为大家介绍了。总之,要养成查看源码API的习惯。 @Target({ java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(Schedules.class) public @interface Scheduled { public abstract String cron(); public abstract String zone(); public abstract long fixedDelay(); public abstract String fixedDelayString(); public abstract long fixedRate(); public abstract String fixedRateString(); public abstract long initialDelay(); public abstract String initialDelayString(); } 项目:http://git.oschina.net/52itstyle/spring-boot-mail 作者: 小柒 出处: https://blog.52itstyle.com 本文版权归作者和云栖社区所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 如有问题, 可邮件(345849402@qq.com)咨询。

优秀的个人博客,低调大师

DARPA 资助开发非冯诺依曼处理器

名为 HIVE(代表 Hierarchical Identify Verify Exploit)的非冯诺依曼处理器得到了美国国防部高级研究计划署(DARPA)的资助。芯片巨人英特尔、高通、国防承包商诺斯格鲁曼、西北太平洋国家实验室和乔治亚理工大学参与了这个项目。 DARPA 的 Microsystems Technology Office (MTO)项目经理 Trung Tran 称,今天的计算机架构仍然是 1940 年代发明的冯诺依曼架构,CPU 和 GPU 已经走向了平行,但其核心仍然是冯诺依曼处理器。HIVE 是首个图解分析处理器,采用了非冯诺依曼方法,它能同时在记忆体的不同区域同时执行不同操作。 它允许一张大的地图能被许多个处理器同时访问,每个处理器使用自己的本地高速缓存在全局记忆体上同时执行分散汇集操作。新的处理器被认为有望大幅减少能耗。 本文转自d1net(转载)

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册