Gowhich

Durban's Blog

今天分享一个可以将汉字转为拼音的 而且也可以加音标的类,

这个要感谢,那些巨人的肩膀啊

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
define('BASE_PATH', dirname(__FILE__));
class Tpinyin {
protected $dict = array();
protected $dictfile = 'pylib.gif';
protected $dictoffs = 244;
protected $tune = array();
private $charset = '';
private $maxlength = 0;
private $fp;
function __construct() {
$this->dictfile = BASE_PATH . '/'. $this->dictfile;
$fp = fopen($this->dictfile, 'rb');
fread($fp, 41);
$this->dict[] = explode(',', fread($fp, 57));
$this->dict[] = explode(',', fread($fp, 146));
}
function settune() {
$tune = array(
'a' => array("\x01\x01","\x00\xe1","\x01\xce","\x00\xe0",),
'e' => array("\x01\x13","\x00\xe9","\x01\x1b","\x00\xe8",),
'i' => array("\x01\x2b","\x00\xed","\x01\xd0","\x00\xec",),
'o' => array("\x01\x4d","\x00\xf3","\x01\xd2","\x00\xf2",),
'u' => array("\x01\x6b","\x00\xfa","\x01\xd4","\x00\xf9",),
'v' => array("\x01\xd6","\x01\xd8","\x01\xda","\x01\xdc",),
);
foreach($tune as $k=>$r)
foreach($r as $i=>$v)
$this->tune[$k][$i] = mb_convert_encoding($v, $this->charset, 'UCS-2');
}
function pinyin($str) {
$this->charset = mb_check_encoding($str, 'UTF-8') ? 'UTF-8' : 'GBK';
// $this->settune();//是否加音标
$this->fp = fopen($this->dictfile, 'rb');
$this->maxlength = filesize($this->dictfile);
$str = mb_convert_encoding($str, "UCS-2", "UTF-8, GBK");
$t = array_map(array($this, 'pinyin_back'), str_split($str, 2));
return join('', $t); //连接成串,要不要自己决定
}
function pinyin_back($ch) {
if(ord($ch{0}) == 0) return $ch{1};
$o = hexdec(bin2hex($ch)) - 0x4e00;
if($o < 0 || $o >= $this->maxlength) return mb_convert_encoding($ch, $this->charset, 'UCS-2');
fseek($this->fp, $o*2 + $this->dictoffs);
$x = sprintf('%05d', current(unpack('S', fread($this->fp, 2))));
$t = $this->dict[0][substr($x, 0, 2)+0] . $this->dict[1][substr($x, 2, 2)+0];
$n = substr($x, -1) - 1;
$s = $t;
foreach($this->tune as $k=>$v) {
$s = str_replace($k, $v[$n], $s);
if($s != $t) break;
}
return "$s";//加了个空格,要不要自己决定
}
}

这个文件是需要一个库的,但是那位大神将库放在了图片里面,我觉得很牛叉,于是就这样用了,呵呵

使用方式如下

1
2
$p = new Tpinyin;
echo $p->pinyin('惘');

结果自己试试就知道了。

如果想控制音标的话,可以考虑是不是加载这个函数settune,有加的话,就会有音标的。

apple官方对EKEventViewController是这么描述的

An EKEventViewController object displays the details of a calendar event. You can set whether users are allowed to edit the event. If the event is an invitation, where the organizer is not the user, you can set whether a calendar preview is shown.

EKEventViewController其实就是一个展示日历事件详情的视图控制器

官方的一段代码的实现是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#pragma mark -
#pragma mark EKEventEditViewDelegate

// Overriding EKEventEditViewDelegate method to update event store according to user actions.
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
{
RootViewController * __weak weakSelf = self;
// Dismiss the modal view controller
[self dismissViewControllerAnimated:YES completion:^
{
if (action != EKEventEditViewActionCanceled)
{
dispatch_async(dispatch_get_main_queue(), ^{
// Re-fetch all events happening in the next 24 hours
weakSelf.eventsList = [self fetchEvents];
// Update the UI with the above events
[weakSelf.tableView reloadData];
});
}
}];
}


// Set the calendar edited by EKEventEditViewController to our chosen calendar - the default calendar.
- (EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents:(EKEventEditViewController *)controller
{
return self.defaultCalendar;
}

并且他的实现过程是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma mark -
#pragma mark Add a new event

// Display an event edit view controller when the user taps the "+" button.
// A new event is added to Calendar when the user taps the "Done" button in the above view controller.
- (IBAction)addEvent:(id)sender
{
// Create an instance of EKEventEditViewController
EKEventEditViewController *addController = [[EKEventEditViewController alloc] init];

// Set addController's event store to the current event store
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self presentViewController:addController animated:YES completion:nil];
}

其实跟自己写一个viewcontroller的过程,然后自己再去调用是差不多的,少的是自己不用去写这个逻辑流程,还有就是,如果自己写的话是不是会有什么限制。我觉得应该不会有,不然也不会开放出来让大家使用。

scopeButtonTitles的使用很简单,就像吃苹果一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)viewDidLoad
{
[super viewDidLoad];

// create a mutable array to contain products for the search results table
self.searchResults = [NSMutableArray arrayWithCapacity:[self.products count]];

// set up the search scope buttons with titles using products' localized display names
NSMutableArray *scopeButtonTitles = [[NSMutableArray alloc] init];
[scopeButtonTitles addObject:NSLocalizedString(@"All", @"Title for the All button in the search display controller.")];

for (NSString *deviceType in [APLProduct deviceTypeNames])
{
NSString *displayName = [APLProduct displayNameForType:deviceType];
[scopeButtonTitles addObject:displayName];
}

self.searchDisplayController.searchBar.scopeButtonTitles = scopeButtonTitles;
}

上面的代码APLProduct这个类你可以在这篇文章中找到答案。NSCoding解释 initWithCoder: encodeWithCoder:

更详细的可以看这里啦

昨天研究了UISearchBar,今天遇到了showsScopeBar问题, 还是继续说一下UISearchBar 吧

UIBarStyle barStyle
控件的样式

id delegate
设置控件的委托

NSString *text
控件上面的显示的文字

NSString *prompt
显示在顶部的单行文字,通常作为一个提示行

NSString *placeholder
半透明的提示文字,输入搜索内容消失

BOOL showsBookmarkButton
是否在控件的右端显示一个书的按钮(没有文字的时候)

BOOL showsCancelButton
是否显示cancel按钮

BOOL showsSearchResultsButton
是否在控件的右端显示搜索结果按钮(没有文字的时候)

BOOL searchResultsButtonSelected
搜索结果按钮是否被选中

UIColor *tintColor
bar的颜色(具有渐变效果)

BOOL translucent
指定控件是否会有透视效果

UITextAutocapitalizationType
autocapitalizationType
设置在什么的情况下自动大写

UITextAutocorrectionType
autocorrectionType
对于文本对象自动校正风格

UIKeyboardType
keyboardType
键盘的样式

NSArray *scopeButtonTitles
搜索栏下部的选择栏,数组里面的内容是按钮的标题

NSInteger selectedScopeButtonIndex
搜索栏下部的选择栏按钮的个数

BOOL showsScopeBar
控制搜索栏下部的选择栏是否显示出来

代理列表:

编辑代理

– searchBar:textDidChange:

– searchBar:shouldChangeTextInRange:replacementText:

– searchBarShouldBeginEditing:

– searchBarTextDidBeginEditing:

– searchBarShouldEndEditing:

– searchBarTextDidEndEditing:

点击按钮

– searchBarBookmarkButtonClicked:

– searchBarCancelButtonClicked:

– searchBarSearchButtonClicked:

– searchBarResultsListButtonClicked:

范围代理

– searchBar:selectedScopeButtonIndexDidChange:

searchBar的范围控件showsScopeBar,官方学名叫Scope Buttons。
首先就要设置这个属性:
self.searchBar.showsScopeBar = YES;
然后要给他添加按钮。比如说,这样:self.searchBar.scopeButtonTitles = [NSArray arrayWithObjects:@”BOY”,@”GIRL”,@”ALL”,nil];
还有一个很重要的事情就是我们要实现这个代理UISearchBarDelegate里的这个方法searchBar:selectedScopeButtonIndexDidChange:。告诉表格,你选择的范围是啥。
还有要是设置默认选择哪个按钮的话,要设置这个属性,像这样就是默认选中第1个啦。
self.searchBar.selectedScopeButtonIndex = 0;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
shouldReloadTableForSearchString:(NSString *)searchString
{
NSLog(@"shouldReloadTableForSearchString: %@", searchString);
if ((controller.searchBar.selectedScopeButtonIndex != 0) || // 第一个search条件
(searchString && [searchString length])) {
[self maybeBeginSearch];
return NO;
} else {
self.currentResult = nil;
return YES;
}
}


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
NSLog(@"shouldReloadTableforSearchScope: %d", searchOption);
if ((searchOption != 0) ||
(controller.searchBar.text && [controller.searchBar.text length])) {
[self maybeBeginSearch];
return NO;
} else {
self.currentResult = nil;
return YES;
}
}

- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
// make the activity indicator a sibling of the tableView, so that it can
// be displayed on top of it
[[tableView superview] addSubview:_activityView];
}

- (void)maybeBeginSearch
{
// cancel any existing timer
if (_searchTimer) {
NSLog(@"Cancelling existing timer");
[_searchTimer invalidate];
[_searchTimer release];
}


// 创建一个timer
_searchTimer = [[NSTimer scheduledTimerWithTimeInterval:0.3
target:self
selector:@selector(beginTimerSearch:)
userInfo:nil
repeats:NO] retain];
}

- (void)beginTimerSearch:(NSTimer*)timer
{
if (timer == _searchTimer) {
[_searchTimer invalidate];
[_searchTimer release];
_searchTimer = nil;
[self beginSearch];
}
}


- (void)beginSearch
{
NSLog(@"Begin search for %@ with scope %d", self.searchDisplayController.searchBar.text,
self.searchDisplayController.searchBar.selectedScopeButtonIndex);

// in case one is running already
[self.currentRequest cancel];
self.currentRequest = nil;

NSInteger scopeIndex = self.searchDisplayController.searchBar.selectedScopeButtonIndex;
if (scopeIndex == 0) {
NSString* searchString = self.searchDisplayController.searchBar.text;

if (searchString && [searchString length]) {
_activityView.hidden = NO;
if ([searchString length]>5 &&
![searchString hasSuffix:@"*"])
searchString = [NSString stringWithFormat:@"%@*", searchString];
self.currentRequest = [[FreebaseSession session] search:searchString
name:@"suggest"
delegate:self
didFinishSelector:@selector(searchFinished:)
options:[NSDictionary dictionaryWithObjectsAndKeys:
@"/common/topic", @"type",
nil]];
}
else
NSLog(@"No search string: %@", searchString);
}
else {
[self beginGeosearch];
}
}


- (void)beginGeosearch {
NSLog(@"beginGeosearch");
_activityLabel.text = @"Locating...";
_activityView.hidden = NO;

// this is what I want to do:
// self.searchDisplayController.searchResultsTableView.hidden = NO;

// this is moronic, but it makes the table display :(
NSString* searchString;
if (![self.searchDisplayController.searchBar.text length])
self.searchDisplayController.searchBar.text = @" ";
else
searchString = self.searchDisplayController.searchBar.text;

if (!_awaitingLocation) {
NSLog(@"Awaiting location, so queing up a search");
_awaitingLocationForSearch = YES;
_awaitingLocation = YES;
[_locationManager startUpdatingLocation];
} else if (!_currentLocation) {
NSLog(@"Not awaiting, but still missing _currentLocation");
// we're awaiting a location, but haven't yet started searching
_awaitingLocationForSearch = YES;
} else {
NSLog(@"Kicking off a geosearch...");
_activityLabel.text = @"Loading...";
_awaitingLocationForSearch = NO;
// ok, we have a location, lets search!
CLLocationDegrees latitude = _currentLocation.coordinate.latitude;
CLLocationDegrees longtitude = _currentLocation.coordinate.longitude;
NSDictionary* geoJsonLocation = [NSDictionary dictionaryWithObjectsAndKeys:
@"Point", @"type",
[NSArray arrayWithObjects:
[NSNumber numberWithDouble:longtitude],
[NSNumber numberWithDouble:latitude], nil],
@"coordinates",
nil];
NSString* locationString = [geoJsonLocation JSONRepresentation];

NSArray *mql_output = [NSArray arrayWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNull null], @"id",
[NSNull null], @"name",
[NSArray arrayWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNull null], @"id",
[NSNull null], @"name",
[NSNumber numberWithBool:YES], @"optional", nil]], @"type",
nil]];

NSString *mql_output_string = [[mql_output JSONRepresentation] retain];
//[{"type": {"optional": "forbidden",
// "id|=": ["/location/country", "/location/us_state", "/location/continent", "/location/us_county"]}}]

NSString* distance = [NSString stringWithFormat:@"%f",
DISTANCES[self.searchDisplayController.searchBar.selectedScopeButtonIndex]];

NSString *searchString = [self.searchDisplayController.searchBar.text
stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];

if (searchString && [searchString length]) {
NSString *geo_filter = [[NSDictionary dictionaryWithObjectsAndKeys:
distance, @"within",
locationString, @"location",
@"relevance", @"order_by",
@"/common/topic", @"type",
@"point", @"geometry_type",
nil] JSONRepresentation];
NSMutableDictionary*
options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
geo_filter, @"geo_filter",
@"/common/topic", @"type",
nil];
if (self.mqlFilter)
[options setObject:self.mqlFilter forKey:@"mql_filter"];

NSLog(@"Search with geo_filter for %@ using %@", searchString, options);
if ([searchString length]>5 &&
![searchString hasSuffix:@"*"])
searchString = [NSString stringWithFormat:@"%@*", searchString];
self.currentRequest = [[FreebaseSession session] search:searchString
name:@"geo_relevance"
delegate:self
didFinishSelector:@selector(searchFinished:)
options:options];

} else {
NSMutableDictionary*
options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
distance, @"within",
@"relevance", @"order_by",
mql_output_string, @"mql_output",
@"/common/topic", @"type",
@"point", @"geometry_type",
nil];
if (self.mqlFilter)
[options setObject:self.mqlFilter forKey:@"mql_filter"];
NSLog(@"Searching geo-only");
self.currentRequest = [[FreebaseSession session] geosearch:locationString
name:@"suggest"
delegate:self
didFinishSelector:@selector(geoSearchFinished:)
options:options];
}

[mql_output_string release];
}
}

-
(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation
*)oldLocation
{
self.currentLocation = newLocation;
NSLog(@"New location! %@", [newLocation description]);

if (_awaitingLocationForSearch) {
_awaitingLocationForSearch = NO;
[self beginGeosearch];
} else {
// ok, we can simply stop at this point -
// it means we've gotten a second location marker,
// possibly more accurate than before - no sense in
// burning the battery. We don't set _awaitingLocation now,
// because the one we've got is good enough
NSLog(@"Got a second location, that's good enough for now.");
[manager stopUpdatingLocation];
}
}



- (void)searchFinished:(id)result
{
NSLog(@"Search complete, %d items", [result count]);
self.currentResult = result;
_activityView.hidden = YES;
[self.searchDisplayController.searchResultsTableView reloadData];
}

- (void)geoSearchFinished:(NSDictionary*)result
{
self.currentResult = [result valueForKeyPath:@"features.properties"];
NSLog(@"Geosearch complete, %d items", [self.currentResult count]);
_activityView.hidden = YES;
[self.searchDisplayController.searchResultsTableView reloadData];
}

- (void)errorDidOccur:(id)result name:(NSString*)name
{
NSLog(@"oops...search error: %@", result);
_activityView.hidden = YES;
self.currentResult = [NSArray arrayWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNull null], @"id",
[NSArray array], @"type",
[NSString stringWithFormat:@"Error: %@", result], @"name",
nil]];
[self.searchDisplayController.searchResultsTableView reloadData];
}

/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/

- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.searchDisplayController setActive:YES animated:YES];
[self.searchDisplayController.searchBar becomeFirstResponder];
}

/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/

1、为了将应用数据存储到硬盘中,iOS提供基本的文件API、Property List序列化、SQLite、CoreData以及NSCoding。对于轻量级的数据要求,NSCoding因其简单而成为一种比较合适的方式。 NSCoding是一个你需要在数据类上要实现的协议以支持数据类和数据流间的编码和解码。数据流可以持久化到硬盘。

2、是类对象本身数据的写入到本地文件。

我们需要实现两个方法: encodeWithCoder和initWithEncoder。encodeWithCoder就是编码,initWithCoder就是解码。 encodeWithCoder方法传入的是一个NSCoder对象,实现的时候我们就可以调用encodeObject、encodeFloat、 encodeInt等各种方法并通过指定键值进行编码。

APLProduct.m的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#import "APLProduct.h"

NSString *ProductTypeDevice = @"Device";
NSString *ProductTypeDesktop = @"Desktop";
NSString *ProductTypePortable = @"Portable";


@implementation APLProduct

+ (instancetype)productWithType:(NSString *)type name:(NSString *)name year:(NSNumber *)year price:(NSNumber *)price
{
APLProduct *newProduct = [[self alloc] init];
newProduct.type = type;
newProduct.name = name;
newProduct.yearIntroduced = year;
newProduct.introPrice = price;

return newProduct;
}

+ (NSArray *)deviceTypeNames
{
static NSArray *deviceTypeNames = nil;
static dispatch_once_t once;

dispatch_once(&once, ^{
deviceTypeNames = @[ProductTypeDevice, ProductTypePortable, ProductTypeDesktop];
});

return deviceTypeNames;
}

+ (NSString *)displayNameForType:(NSString *)type
{
static NSMutableDictionary *deviceTypeDisplayNamesDictionary = nil;
static dispatch_once_t once;

dispatch_once(&once, ^{
deviceTypeDisplayNamesDictionary = [[NSMutableDictionary alloc] init];
for (NSString *deviceType in [self deviceTypeNames])
{
NSString *displayName = NSLocalizedString(deviceType, @"dynamic");
deviceTypeDisplayNamesDictionary[deviceType] = displayName;
}
});

return deviceTypeDisplayNamesDictionary[type];
}


#pragma mark - Archiving

static NSString *NameKey = @"NameKey";
static NSString *TypeKey = @"TypeKey";
static NSString *YearKey = @"YearKey";
static NSString *PriceKey = @"PriceKey";

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_name = [aDecoder decodeObjectForKey:NameKey];
_type = [aDecoder decodeObjectForKey:TypeKey];
_yearIntroduced = [aDecoder decodeObjectForKey:YearKey];
_introPrice = [aDecoder decodeObjectForKey:PriceKey];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:NameKey];
[aCoder encodeObject:self.type forKey:TypeKey];
[aCoder encodeObject:self.yearIntroduced forKey:YearKey];
[aCoder encodeObject:self.introPrice forKey:PriceKey];
}

@end

APLProduct.h的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extern NSString *ProductTypeDevice;
extern NSString *ProductTypeDesktop;
extern NSString *ProductTypePortable;


@interface APLProduct : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSNumber *yearIntroduced;
@property (nonatomic) NSNumber *introPrice;

+ (instancetype)productWithType:(NSString *)type name:(NSString *)name year:(NSNumber *)year price:(NSNumber *)price;

+ (NSArray *)deviceTypeNames;
+ (NSString *)displayNameForType:(NSString *)type;

@end

程序本地化是扩展应用市场的重要砝码.iOS提供了简便的方法来实现本地化,其中用的最多的就是NSLocalizedString.

首先查看下NSLocalizedString是什么:

1
2
3
4
5
6
7
8
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \
[bundle localizedStringForKey:(key) value:(val) table:(tbl)]

这里我们只看第一个

这是一个宏,本质上是调用了函数 locakizedStrigForKey:.这样,这个宏做的其实就是在当前bundle中查找资源文件名Localizable.strings

中键值key所指向的字符串.这样就不难理解还有诸如:NSLocalizedStringFromTable的宏了.

下面我们就来具体实现一下.

新建任一工程,然后添加新文件Localizable.strings

然后选择文件属性中的”Make File Localizable”,页面自然跳转,再选择”General”选项卡时就会发现”Add Localization”了.

默认有English,我们可以添加zh-hans ,然后在相应的文件中输入: “NAME” = “你好”,这样在代码中只需要简单的调用:

1
nameLabel.text = NSLocalizedString(@"NAME",nil);

此时在工程文件下出现了 *.lpjo的文件夹,下面安置了相应的本地化文件.由此可以判断,对于其他资源文件如图片,xib文件都可以进行本地化.

最后,我们再实现对程序名称的本地化.

在工程的info.plist文件的属性中选择”Make File Localizable”,然后会发现工程下出现InfoPlist.strings的文件,如法炮制,添加zh-hans,并在

相应的文件中添加”CFBundleDisplayName” = “中文名称” 即可.这样,你会发现你的机器上程序名称变成了中文.

PS:我还遇到一个问题,就是在本地化的时候语言代码是需要手工添加的,apple的文档上说所有的语言代码可以从ISO639( http://www.loc.gov/standards/iso639-2/php/English\_list.php)查询,可这个列表上中文对应的是chi/zho.而这显然没有区分简体和繁体中文.

dispatch_once 在ios中是用来创建单例的,具体为什么要创建单例,咱先不讨论,咱先看看,这个要怎么使用。

利用dispatch_once创建单例

在开发中我们会用到NSNotificationCenter、NSFileManager等,获取他们的实例通过[NSNotificationCenter defaultCenter][NSFileManager defaultManager]来获取,其实这就是单例。

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

接下来我们来实现自己的单例,这里有一个TestManager类,为这个类实现单例

1
2
3
4
5
6
7
8
9
10
11
+(TestManager *)sharedInstance
{
static TestManager *sharedManager;

static dispatch_once_t once;
dispatch_once(&once, ^{
sharedManager = [[TestManager alloc] init];
});

return sharedManager;
}

到目前为止,我们就实现了一个单例,一切就搞定了,是不是很简单!

使用就按照如下方式获取唯一实例即可:

1
TestManager *testManager = [TestManager sharedInstance];

讨论dispatch_once函数实现单例的方法就这样结束啦,呵呵

今天看代码的时候,遇到了一个问号,跟自己没有好好学c有关的,或者是学了不用就忘记了。

1
2
3
extern NSString *ProductTypeDevice;
extern NSString *ProductTypeDesktop;
extern NSString *ProductTypePortable;

关键字extern于是就有了下文。

1,基本解释
  extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
  另外,extern也可用来进行链接指定。

2,问题:extern 变量
  在一个源文件里定义了一个数组:char a[6];
  在另外一个文件里用下列语句进行了声明:extern char *a;
  请问,这样可以吗?
  答案与分析:
  1)、不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的指针并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]
  2)、例子分析如下,如果a[] = "abcd",则外部变量a=0x61626364 (abcd的ASCII码值),*a显然没有意义
  显然a指向的空间(0x61626364)没有意义,易出现非法内存访问。
  3)、这提示我们,在使用extern时候要严格对应声明时的格式,在实际编程中,这样的错误屡见不鲜。
  4)、extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。

4,问题:extern 函数2
  当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的extern申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会照成系统错误,这种情况应该如何解决?
  答案与分析:
  目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用方include该头文件,从而省去extern这一步。以避免这种错误。
  宝剑有双锋,对extern的应用,不同的场合应该选择不同的做法。

5,问题:extern “C”
  在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?

  答案与分析:
  C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
  下面是一个标准的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//在.h文件的头上
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
 #endif /* __cplusplus */
 …
 …
 //.h文件结束的地方
 #ifdef __cplusplus
 #if __cplusplus
}
#endif
#endif /* __cplusplus */

6, 问题:extern 函数1
  常常见extern放在函数的前面成为函数声明的一部分,那么,C语言的关键字extern在函数的声明中起什么作用?
  答案与分析:
  如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有明显的区别:
extern int f(); 和int f();
  当然,这样的用处还是有的,就是在程序中取代include “*.h”来声明函数,在一些复杂的项目中,我比较习惯在所有的函数声明前添加extern修饰。

关于iOS6 UI状态保持和恢复,是最近看到几个例子,里面有这个方法encodeRestorableStateWithCoderdecodeRestorableStateWithCoder,感觉很奇怪,都怪自己知识浅薄啊

其实呢使用这个是有原因的.

iOS设计规范中要求,当应用退出的时候(包括被终止运行时候),画面中UI元素状态需要保持的,当再次进来的时候看状态与退出是一样的。iOS6之后苹果提供以下API使得UI状态保持和恢复变得很容易了。
在iOS6中我们可以在3地方实现状态保持和恢复:

1,应用程序委托对象

2,视图控制器

3,自定义视图

恢复标识是iOS6为了实现UI状态保持和恢复添加的设置项目。我们需要在应用程序委托对象AppDelegate代码部分做一些修改,添加的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-(BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder  
{

return YES;

}

-(BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{

return YES;

}

- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder
{

[coder encodeFloat:2.0 forKey:@"Version"];

}

- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder
{

float lastVer = [coder decodeFloatForKey:@"Version"];

NSLog(@”lastVer = %f”,lastVer);

}

其中application:shouldSaveApplicationState:在应用退出的时候调用,负责控制是否允许保存状态,返回YES情况是可以保存,NO是不保存。

application:shouldRestoreApplicationState:是应用启动时候调用,负责控制是否恢复上次退出的时候的状态,返回YES情况是可以恢复,NO是不恢复。

application:willEncodeRestorableStateWithCoder:方法是保存时候调用,在这个方法中实现UI状态或数据的保存,其中[coder encodeFloat:2.0 forKey:@"Version"]是保存简单数据。

application:didDecodeRestorableStateWithCoder:方法是恢复时候调用,在这个方法中实现UI状态或数据的恢复,其中[coder decodeFloatForKey:@"Version"]语句是恢复上次保存的数据。

要想实现具体画面中控件的保持和恢复,还需要在它视图控制器中添加一些代码,ViewController.m中添加的代码如下:

1
2
3
4
5
6
7
8
9
10
11
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder  
{
[super encodeRestorableStateWithCoder:coder];
[coder encodeObject:self.txtField.text forKey:kSaveKey];
}

-(void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
[super decodeRestorableStateWithCoder:coder];
self.txtField.text = [coder decodeObjectForKey:kSaveKey];
}

在iOS6之后视图控制器都添加了两个:encodeRestorableStateWithCoder:decodeRestorableStateWithCoder:用来实现该控制器中的控件或数据的保存和恢复。其中encodeRestorableStateWithCoder: 方法是在保存时候调用,[coder encodeObject:self.txtField.text forKey:kSaveKey]语句是按照指定的键保存文本框的内容,decodeRestorableStateWithCoder:方法是在恢复时候调用,[coder decodeObjectForKey:kSaveKey]是恢复文本框内容时候调用,保存和恢复事实上就是向一个归档文件中编码和解码的过程。

找了个觉得很稀奇的东西,不错,就是汉字转拼音的类库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php
/**
* 汉字转拼音函数类
*/
class Helper_Pinyin{
static public function Pinyin($_String, $_Code='UTF8'){ //GBK页面可改为gb2312,其他随意填写为UTF8
$_DataKey = "a|ai|an|ang|ao|ba|bai|ban|bang|bao|bei|ben|beng|bi|bian|biao|bie|bin|bing|bo|bu|ca|cai|can|cang|cao|ce|ceng|cha".
"|chai|chan|chang|chao|che|chen|cheng|chi|chong|chou|chu|chuai|chuan|chuang|chui|chun|chuo|ci|cong|cou|cu|".
"cuan|cui|cun|cuo|da|dai|dan|dang|dao|de|deng|di|dian|diao|die|ding|diu|dong|dou|du|duan|dui|dun|duo|e|en|er".
"|fa|fan|fang|fei|fen|feng|fo|fou|fu|ga|gai|gan|gang|gao|ge|gei|gen|geng|gong|gou|gu|gua|guai|guan|guang|gui".
"|gun|guo|ha|hai|han|hang|hao|he|hei|hen|heng|hong|hou|hu|hua|huai|huan|huang|hui|hun|huo|ji|jia|jian|jiang".
"|jiao|jie|jin|jing|jiong|jiu|ju|juan|jue|jun|ka|kai|kan|kang|kao|ke|ken|keng|kong|kou|ku|kua|kuai|kuan|kuang".
"|kui|kun|kuo|la|lai|lan|lang|lao|le|lei|leng|li|lia|lian|liang|liao|lie|lin|ling|liu|long|lou|lu|lv|luan|lue".
"|lun|luo|ma|mai|man|mang|mao|me|mei|men|meng|mi|mian|miao|mie|min|ming|miu|mo|mou|mu|na|nai|nan|nang|nao|ne".
"|nei|nen|neng|ni|nian|niang|niao|nie|nin|ning|niu|nong|nu|nv|nuan|nue|nuo|o|ou|pa|pai|pan|pang|pao|pei|pen".
"|peng|pi|pian|piao|pie|pin|ping|po|pu|qi|qia|qian|qiang|qiao|qie|qin|qing|qiong|qiu|qu|quan|que|qun|ran|rang".
"|rao|re|ren|reng|ri|rong|rou|ru|ruan|rui|run|ruo|sa|sai|san|sang|sao|se|sen|seng|sha|shai|shan|shang|shao|".
"she|shen|sheng|shi|shou|shu|shua|shuai|shuan|shuang|shui|shun|shuo|si|song|sou|su|suan|sui|sun|suo|ta|tai|".
"tan|tang|tao|te|teng|ti|tian|tiao|tie|ting|tong|tou|tu|tuan|tui|tun|tuo|wa|wai|wan|wang|wei|wen|weng|wo|wu".
"|xi|xia|xian|xiang|xiao|xie|xin|xing|xiong|xiu|xu|xuan|xue|xun|ya|yan|yang|yao|ye|yi|yin|ying|yo|yong|you".
"|yu|yuan|yue|yun|za|zai|zan|zang|zao|ze|zei|zen|zeng|zha|zhai|zhan|zhang|zhao|zhe|zhen|zheng|zhi|zhong|".
"zhou|zhu|zhua|zhuai|zhuan|zhuang|zhui|zhun|zhuo|zi|zong|zou|zu|zuan|zui|zun|zuo";
$_DataValue = "-20319|-20317|-20304|-20295|-20292|-20283|-20265|-20257|-20242|-20230|-20051|-20036|-20032|-20026|-20002|-19990".
"|-19986|-19982|-19976|-19805|-19784|-19775|-19774|-19763|-19756|-19751|-19746|-19741|-19739|-19728|-19725".
"|-19715|-19540|-19531|-19525|-19515|-19500|-19484|-19479|-19467|-19289|-19288|-19281|-19275|-19270|-19263".
"|-19261|-19249|-19243|-19242|-19238|-19235|-19227|-19224|-19218|-19212|-19038|-19023|-19018|-19006|-19003".
"|-18996|-18977|-18961|-18952|-18783|-18774|-18773|-18763|-18756|-18741|-18735|-18731|-18722|-18710|-18697".
"|-18696|-18526|-18518|-18501|-18490|-18478|-18463|-18448|-18447|-18446|-18239|-18237|-18231|-18220|-18211".
"|-18201|-18184|-18183|-18181|-18012|-17997|-17988|-17970|-17964|-17961|-17950|-17947|-17931|-17928|-17922".
"|-17759|-17752|-17733|-17730|-17721|-17703|-17701|-17697|-17692|-17683|-17676|-17496|-17487|-17482|-17468".
"|-17454|-17433|-17427|-17417|-17202|-17185|-16983|-16970|-16942|-16915|-16733|-16708|-16706|-16689|-16664".
"|-16657|-16647|-16474|-16470|-16465|-16459|-16452|-16448|-16433|-16429|-16427|-16423|-16419|-16412|-16407".
"|-16403|-16401|-16393|-16220|-16216|-16212|-16205|-16202|-16187|-16180|-16171|-16169|-16158|-16155|-15959".
"|-15958|-15944|-15933|-15920|-15915|-15903|-15889|-15878|-15707|-15701|-15681|-15667|-15661|-15659|-15652".
"|-15640|-15631|-15625|-15454|-15448|-15436|-15435|-15419|-15416|-15408|-15394|-15385|-15377|-15375|-15369".
"|-15363|-15362|-15183|-15180|-15165|-15158|-15153|-15150|-15149|-15144|-15143|-15141|-15140|-15139|-15128".
"|-15121|-15119|-15117|-15110|-15109|-14941|-14937|-14933|-14930|-14929|-14928|-14926|-14922|-14921|-14914".
"|-14908|-14902|-14894|-14889|-14882|-14873|-14871|-14857|-14678|-14674|-14670|-14668|-14663|-14654|-14645".
"|-14630|-14594|-14429|-14407|-14399|-14384|-14379|-14368|-14355|-14353|-14345|-14170|-14159|-14151|-14149".
"|-14145|-14140|-14137|-14135|-14125|-14123|-14122|-14112|-14109|-14099|-14097|-14094|-14092|-14090|-14087".
"|-14083|-13917|-13914|-13910|-13907|-13906|-13905|-13896|-13894|-13878|-13870|-13859|-13847|-13831|-13658".
"|-13611|-13601|-13406|-13404|-13400|-13398|-13395|-13391|-13387|-13383|-13367|-13359|-13356|-13343|-13340".
"|-13329|-13326|-13318|-13147|-13138|-13120|-13107|-13096|-13095|-13091|-13076|-13068|-13063|-13060|-12888".
"|-12875|-12871|-12860|-12858|-12852|-12849|-12838|-12831|-12829|-12812|-12802|-12607|-12597|-12594|-12585".
"|-12556|-12359|-12346|-12320|-12300|-12120|-12099|-12089|-12074|-12067|-12058|-12039|-11867|-11861|-11847".
"|-11831|-11798|-11781|-11604|-11589|-11536|-11358|-11340|-11339|-11324|-11303|-11097|-11077|-11067|-11055".
"|-11052|-11045|-11041|-11038|-11024|-11020|-11019|-11018|-11014|-10838|-10832|-10815|-10800|-10790|-10780".
"|-10764|-10587|-10544|-10533|-10519|-10331|-10329|-10328|-10322|-10315|-10309|-10307|-10296|-10281|-10274".
"|-10270|-10262|-10260|-10256|-10254";
$_TDataKey = explode('|', $_DataKey);
$_TDataValue = explode('|', $_DataValue);
$_Data = array_combine($_TDataKey, $_TDataValue);
arsort($_Data);
reset($_Data);
if($_Code!= 'gb2312') $_String = self::_U2_Utf8_Gb($_String);
$_Res = '';
for($i=0; $i<strlen($_String); $i++) {
$_P = ord(substr($_String, $i, 1));
if($_P>160) {
$_Q = ord(substr($_String, ++$i, 1)); $_P = $_P*256 + $_Q - 65536;
}
$_Res .= self::_Pinyin($_P, $_Data);
}
return preg_replace("/[^a-z0-9]*/", '', $_Res);
}

static public function _Pinyin($_Num, $_Data){
if($_Num>0 && $_Num<160 ){
return chr($_Num);
}elseif($_Num<-20319 || $_Num>-10247){
return '';
}else{
foreach($_Data as $k=>$v){ if($v<=$_Num) break; }
return $k;
}
}

static public function _U2_Utf8_Gb($_C){
$_String = '';
if($_C < 0x80){
$_String .= $_C;
}elseif($_C < 0x800) {
$_String .= chr(0xC0 | $_C>>6);
$_String .= chr(0x80 | $_C & 0x3F);
}elseif($_C < 0x10000){
$_String .= chr(0xE0 | $_C>>12);
$_String .= chr(0x80 | $_C>>6 & 0x3F);
$_String .= chr(0x80 | $_C & 0x3F);
}elseif($_C < 0x200000) {
$_String .= chr(0xF0 | $_C>>18);
$_String .= chr(0x80 | $_C>>12 & 0x3F);
$_String .= chr(0x80 | $_C>>6 & 0x3F);
$_String .= chr(0x80 | $_C & 0x3F);
}
return iconv('UTF-8', 'GB2312', $_String);
}
}

?>

axure rp pro 5.6 以上

用户名:IloveyouAxure
注册码:UChpuxwbDW6eAIaAf9UujEFSBwN3vpEz9snHvlCQVJGQy4p7WrCyKLLvV5QLvqva

我的是Axure RP Pro 6版本,key网上找的是5.6的,也能用

0%