当前位置:  编程技术>移动开发
本页文章导读:
    ▪项目后对objective-c 单例懂得        项目后对objective-c 单例理解 在做zon项目中,单例都是:   @implementation AppShareDataManager static AppShareDataManager * shareDataManager = nil; @synthesize theCurrentLanguage; @synthesize presentModalFlag; .......... +(AppSha.........
    ▪ 多IDC环境上的分布式id分配方案(转)        多IDC环境下的分布式id分配方案(转) id分配的几种方式 方式一:单点自增分配。全局由一个模块来负责生成id,可保证id从0开始连续递增,数据一般放在本地文件。简洁,但致命的问题是单点.........
    ▪ Axure[第二课]兑现点击按钮增减效果       Axure[第二课]实现点击按钮增减效果 第一步:添加界面,并给文本框设置标签:input  如下图:[img][/img]第二步:选中+号按钮,在交互界面选择onClic(点击时),进入界面:[img][/img]选择界面上的.........

[1]项目后对objective-c 单例懂得
    来源: 互联网  发布时间: 2014-02-18
项目后对objective-c 单例理解

在做zon项目中,单例都是:

 

@implementation AppShareDataManager

static AppShareDataManager * shareDataManager = nil;

@synthesize theCurrentLanguage;
@synthesize presentModalFlag;
..........

+(AppShareDataManager *) sharedManager
{
	if( shareDataManager == nil )
	{
		shareDataManager = [ [ AppShareDataManager alloc ] init ];
	}
	return shareDataManager;
}

-(id)init{
    self = [super init];
    
    if(self){
        //对象实例初始化
        theCurrentLanguage = [ZONUserDefaultManager getAppDefaultLanguage];
      ........
    }
    
    return self;
}

 

 

调试发现

AppShareDataManager *A = [[AppShareDataManager alloc] init];

NSLog(@"A:%@",A);

AppShareDataManager *B = [AppShareDataManager sharedManager];

NSLog(@"B:%@",B);

打印出的是

 

2013-02-28 23:27:25.368 ZON2012[10647:c07] A:<AppShareDataManager: 0x12638630>

2013-02-28 23:27:25.369 ZON2012[10647:c07] B:<AppShareDataManager: 0xb584b40>

 

不是一个内存地址,也就是不是同一个实体!

 

这是apple官方的一个单例建议:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32  

大致如下:

 

/* Singleton.h */
#import &lt;Foundation/Foundation.h&gt;

@interface Singleton : NSObject
+ (Singleton *)instance;
@end

/* Singleton.m */
#import "Singleton.h"
static Singleton *instance = nil;

@implementation Singleton

+ (Singleton *)instance {
    if (!instance) {
        instance = [[super allocWithZone:NULL] init];
    }
    return instance;
}

+ (id)allocWithZone:(NSZone *)zone {
    return [self instance];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)init {
    if (instance) {
        return instance;
    }
    self = [super init];
    return self;
}

- (id)retain {
    return self;
}

- (oneway void)release {
    // Do nothing
}

- (id)autorelease {
    return self;
}

- (NSUInteger)retainCount {
    return NSUIntegerMax;
}

@end

 这是一种很标准的Singleton实现,中规中矩。不过这种实现并不是线程安全的。所以各路大神都各显神威,给出了多种单例模式的实现。

 

现在把他加强下:

 

static MyClass *class = nil;

@implementation MyClass

+(MyClass *)sharedMyClass{
    @synchronized(self){  //为了确保多线程情况下,仍然确保实体的唯一性
        if (!class) {
            [[self alloc] init]; //该方法会调用 allocWithZone
        }
    }
    return class;
}
+(id)allocWithZone:(NSZone *)zone{
    @synchronized(self){// //为了确保多线程情况下,仍然确保实体的唯一性
        if (!class) {
            class = [super allocWithZone:zone]; //确保使用同一块内存地址
            return class;
        }
    }
    return nil;
}

-(id)init
{
  if(class){
     return class;
  }
  if(self = [super init]){
   //进行一些初始化
   }
   return self ;
} 
- (id)copyWithZone:(NSZone *)zone;{
    return self; //确保copy对象也是唯一
}

-(id)retain{
    return self; //确保计数唯一
}

- (unsigned)retainCount
{
   return UINT_MAX;  //装逼用的,这样打印出来的计数永远为-1
}

- (id)autorelease
{
    return self;//确保计数唯一
} 

- (oneway void)release
{
     //重写计数释放方法 do nothing
}
@end

 再调试

MyClass *A = [[MyClass alloc] init];

NSLog(@"A:%@",A);

MyClass *B = [MyClass sharedMyClass];

NSLog(@"B:%@",B);

MyClass *C = [A copy];

NSLog(@"C:%@",C);

打印出的是

A:<MyClass: 0x6a1e130>

B:<MyClass: 0x6a1e130>

C:<MyClass: 0x6a1e130>

都是指向同一块内存地址

 

-----------------------------------切糕分割线--------------------

然而这个人(http://eschatologist.net/blog/?p=178)觉的繁琐,所以给出如下实现:

@interface SomeManager : NSObject
+ (id)sharedManager;
@end

/* 非线程安全的实现 */
@implementation SomeManager

+ (id)sharedManager {
    static id sharedManager = nil;

    if (sharedManager == nil) {
        sharedManager = [[self alloc] init];
    }

    return sharedManager;
}
@end

/* 线程安全的实现 */
@implementation SomeManager

static id sharedManager = nil;

+ (void)initialize {
    if (self == [SomeManager class]) {
        sharedManager = [[self alloc] init];
    }
}

+ (id)sharedManager {
    return sharedManager;
}
@end

 -----------------------------------切糕分割线--------------------

自苹果引入了Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0)后,利用GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)实现单例。

+(SchoolManager *)sharedInstance
{
    __strong static SchoolManager *sharedManager;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedManager = [[SchoolManager alloc] init];
    });
    
    return sharedManager;
}

 函数void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词,第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全的。

看到如下一篇文章,用宏实现(https://gist.github.com/lukeredpath/1057420):

ExampleClass.m

 

@implementation MySharedThing
 
+ (id)sharedInstance
{
DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
return [[self alloc] init];
});
}
 
@end

 

 

GCDSingleton.h

 

#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \
static dispatch_once_t pred = 0; \
__strong static id _sharedObject = nil; \
dispatch_once(&pred, ^{ \
_sharedObject = block(); \
}); \
return _sharedObject; \

 

 

 

 

 

 

 

 

 

1 楼 啸笑天 12 小时前  
Just wanted to say thanks. I too created a macro on the same premise to be a bit more generic:


/*!
* @function Singleton GCD Macro
*/
#ifndef SINGLETON_GCD
#define SINGLETON_GCD(classname)                        \
                                                        \
+ (classname *)shared##classname {                      \
                                                        \
    static dispatch_once_t pred;                        \
    __strong static classname * shared##classname = nil;\
    dispatch_once( &pred, ^{                            \
        shared##classname = [[self alloc] init]; });    \
    return shared##classname;                           \
}                                                          
#endif
This assumes the init is a standard init.

Then to implement in the .h


@interface MyClass : NSObject
+ (MyClass *) sharedMyClass;
@end
and in the .m


#import "MyClass.h"

@implementation MyClass

SINGLETON_GCD(MyClass);

- (id) init {
    if ( (self = [super init]) ) {
        // Initialization code here.
    }  
    return self;
}
@end
I assume that __strong is not necessary if this is a Mac OS X app?
Also, allocWithZone can be ignored when using Garbage Collection?

Thanks again...
2 楼 啸笑天 12 小时前  
//
//  SynthesizeSingleton.h
//  CocoaWithLove
//
//  Created by Matt Gallagher on 20/10/08.
//  Copyright 2009 Matt Gallagher. All rights reserved.
//
//  Permission is given to use this source code file without charge in any
//  project, commercial or otherwise, entirely at your risk, with the condition
//  that any redistribution (in part or whole) of source code must retain
//  this copyright and permission notice. Attribution in compiled projects is
//  appreciated but not required.
//

#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
    @synchronized(self) \
    { \
        if (shared##classname == nil) \
        { \
            shared##classname = [[self alloc] init]; \
        } \
    } \
     \
    return shared##classname; \
} \
\
+ (id)allocWithZone:(NSZone *)zone \
{ \
    @synchronized(self) \
    { \
        if (shared##classname == nil) \
        { \
            shared##classname = [super allocWithZone:zone]; \
            return shared##classname; \
        } \
    } \
     \
    return nil; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
    return self; \
} \
\
- (id)retain \
{ \
    return self; \
} \
\
- (NSUInteger)retainCount \
{ \
    return NSUIntegerMax; \
} \
\
- (void)release \
{ \
} \
\
- (id)autorelease \
{ \
    return self; \
}

    
[2] 多IDC环境上的分布式id分配方案(转)
    来源: 互联网  发布时间: 2014-02-18
多IDC环境下的分布式id分配方案(转)

id分配的几种方式

方式一:单点自增分配。全局由一个模块来负责生成id,可保证id从0开始连续递增,数据一般放在本地文件。简洁,但致命的问题是单点故障会导致服务整体不可用。

方式一改进:为该模块提供主从复制的能力,或者干脆将数据放在mysql里,利用mysql的主从复制,都一定程度上增强了可用性,减轻了单点故障的影响。

方式二:随机/散列分配。通过一些hash算法,比如以时间+随机串为key的md5生成一个唯一的id,关键点在于算法和key的选择要避免冲突。

最典型的就是UUID,UUID的标准型式包含32个16进位数字,以连字号分为五段,形式为8-4-4-4-12的32个字符,如550e8400-e29b-41d4-a716-446655440000。libuuid提供了以时间或者随机数为基的UUID。UUID的最大缺点是位数太长,128位,在绝大多数应用和语言里对128位整数的支持都不好。

方式二改进:有条件的进行压缩。twitter的snowflake使用 time – 41 bits + configured machine id – 10 bits + sequence number – 12 bits的形式分配id,共63位,最高部分使用毫秒级的时间戳,保证了一定程度的有序性,机器标示使用10位,最多可容纳1024个分配器,最后的12位序列号可以支持在1ms内产生4096个不重复的id。从工程角度,这些都足够用了。但对系统时间的依赖性非常强,需要关闭ntp的时间同步功能,或者当检测到ntp时间调整后,拒绝分配id。

 

我们的需求和多IDC的挑战

我们的实际情况是:

· 一些老模块依赖于从0开始自增的id,数据在内存或者文件中以id为偏移来存储的。

· 一些系统依赖于id的增长做数据分片,例如按取除后分表,因此要求id在整体上是比较均衡的增长。

· 在多IDC环境,高延迟加不稳定的网络环境,要求各个分配器彼此之间无需协作,或者可以容忍短期内不可协作。

· 对于一些古董级的老系统来说,还在使用32位的id,63位id还是太大了。

因此,我们需要一种分布式高可用、从0开始自增、基本均衡、能够兼容老系统的id分配方案。

取模或分段的分布式分配

基于方案一再改进一步,将整个id空间按取模或分段等分为若干个独立的id子空间,每个id子空间由一个独立的分配器负责。

优点:简单,各个id分配器无需协作,即使发生网络划分时,也可保证可用性和id的不冲突。

如果在国际化环境的多IDC里进行部署,需要预先将id空间划分为N份,每个国家里部署若干份。每个IDC内应用只连本IDC的id分配服务。

在均衡性上的不足:在同一个IDC内,均衡性可以在接入层均衡算法保证,但是在多个IDC里,ID分配器个数的比例和id增长的服务往往是不吻合的,因此在多个IDC内,id是无法保证均衡增长的。

均衡性上的改进

将id分配分为两层:

· 上层的“id分配器”对应用暴露,提供一次申请一个id的接口,一般本IDC的应用只连本IDC的id分配器。

·下层的“段分配器”对“id分配器”提供服务。id分配器“知晓”所有IDC的所有段分配器的存在,使用均衡策略向段分配器申请一个id段,当所持有的id段快耗尽时,再请求下一个段。

唯一性:全局中,根据分片规则,每个段分配器会持有不同的id段。例如下表中,每个段的大小是100,段分配器A持有分片0和分片1。对于每个分片而言,是一个个跳跃的id段。特殊的,当段大小为1时,段分配器就是改进前的id分配器。

均衡策略:均衡策略在id分配器来实现,简单的讲,是一个轮询策略。每个id分配器会轮询下游段分配器的状态,并选中id段的最小的那个,然后发起id段申请。由于不会加锁,当多个id分配器同时竞争时,可能会出现获取的id段不是全局最小的,可以附加一些策略来调优,比如再多获取一次,并本地排序。从整体上而言,id还是比较均衡的,可满足需求。

可用性:当发生网络划分时,本IDC的id分配器可以只连接本IDC的段分配器,成功的申请到id段。整个系统可容忍一定时间内不可协作,长时间不可协作的唯一危害是id增长不均衡,此时,就退化为改进前的方案。

多IDC环境的适应性:id分配器需要和所有IDC的段分配器交互,但是交互频率很低,同时和提供id分配服务是两个独立的阶段,不会受到多IDC网络环境的干扰。

效果

改进后的id分配方案成功的满足了图片系统重构过程中的兼容需求,并且部署在全球多个IDC内为图片系统提供全局唯一的id分配服务。


    
[3] Axure[第二课]兑现点击按钮增减效果
    来源: 互联网  发布时间: 2014-02-18
Axure[第二课]实现点击按钮增减效果

第一步:添加界面,并给文本框设置标签:input  如下图:
[img]

[/img]



第二步:选中+号按钮,在交互界面选择onClic(点击时),进入界面:
[img]

[/img]

选择界面上的编辑条件,如下图所示:
[img]

[/img]

然后选择第2步:添加动作 中的 部件与变量中的  设置变量/部件值,设置成如下图所示:
[img]

[/img]

添加完条件与动作后,选中+号按钮,交互界面如下:
[img]

[/img]


第三步(-号按钮)与第二步大同小异,只是条件稍微修改下,改为:大于等于1;input控件的值改为:
[[number-1]];
条件:
[img]

[/img]
动作:
[img]

[/img]


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3