工作记录8:iOS 传值问题总结(7种传值完美介绍)

1、属性传值

前向后传值。

记住:

/*

1: 属性传值第一步需要用到什么类型就定义什么样的属性

2: 从上一个页面到一个页面的选中方法里面将要传的值传到来(上一个页面)备注:这种方法只适用于上一个页面推到下一个页面

*/

MainViewController与SecondViewController两个视图 控制器 ,点击MainViewController中的按钮将跳转到SecondViewController视图,同时想要传递一个值过去。这时可以利用属性传值。

首先SecondViewController视图中需要有一个属性用来 存储 传递过来的值:

@property(nonatomic,retain) NSString *firstValue ;//属性传值

然后MainViewController视图需要引用SecondViewController视图的头文件,在视图中的按钮点击事件中,通过SecondViewController的对象将需要传递的值存在firstValue中:

(void)buttonAction:(UIButton *)button
{
SecondViewController *second = 
[[SecondViewController alloc]init];//用下一个视图的属性接受想要传过去的值,属性传值
second.firstValue = _txtFiled.text;
[self.navigationController pushViewController:second animated:YES];
}

页面跳转之后,就能在SecondViewController视图中,通过存值的属性,取用刚才传递过来的值:

//显示传过来的值[_txtFiled setText:_firstValue];//firstValue保存传过来的值

2、方法传值:

需求同一中的 属性传值 一样,但是要通过使用方法传值,可以直接将方法与初始化方法合并,此时当触发MainViewController的按钮点击事件并跳转到 SecondViewController时,在按钮点击事件中可以直接通过SecondViewController的初始化,将值保存在 firstValue中:

初始化方法如下:                首先SecondViewController视图中需要有一个属性用来 存储 传递过来的值:

@property(nonatomic,retain) NSString *firstValue ;//传值用

//重写初始化方法,用于传值
- (id)initWithValue:(NSString *)value
{
if(self = [super initWithNibName:nil bundle:nil]) {
                 self.firstValue = value;
            }
        return self;
}

方法传值:

- (void)buttonAction:(UIButton *)button
{//将方法传值与初始化写到一起
SecondViewController *second = [[SecondViewController alloc]
initWithValue:_txtFiled.text];//此时已经将值存在firstValue中
[self.navigationController pushViewController:second animated:YES];
}

这样就可以直接通过firstValue属性获得传递过来的值:

//显示传过来的值[_txtFiled setText:_firstValue];//firstValue保存传过来的值

3、协议传值   代替协议代理传值,主要时间点问题。

上面 中说明了如何从A传值到B,这次要讲的是如何从A进入B,在B输入值后回传给A,这类似于Android中的利用 Activity的onActivityResult回调方法实现两个Activity之间的值传递,那么在IOS中如何实现这个功能呢,答案是使用 Delegate(委托协议)。

工程结构如下:

其中有两个ViewController分别对应两个界面,一个协议PassValueDelegate用来实现传值协议,UserEntity是传递数据的对象。

以下是实现的效果:点击Open进入Second界面,输入完毕点击OK后回到First界面并显示结果


 

协议中声明的方法:

copy

  1. #import <Foundation/Foundation.h>
  2. @ class
     UserEntity;
  3. @protocol PassValueDelegate <NSObject>
  4. -( void
    )passValue:(UserEntity *)value;
  5. @end
  6. 在第一个窗口实现协议:
  1. #import <UIKit/UIKit.h>
  2. #import "PassValueDelegate.h"
  3. //第一个窗口遵守PassValueDelegate
  4. @interface ViewController : UIViewController<PassValueDelegate>
  5. @property (retain, nonatomic) IBOutlet UILabel *nameLabel;
  6. @property (retain, nonatomic) IBOutlet UILabel *ageLabel;
  7. @property (retain, nonatomic) IBOutlet UILabel *gendarLabel;
  8. - (IBAction)openBtnClicked:(id)sender;
  9. @end

.m文件中实现协议的方法:

[cpp]view plaincopy

  1. //实现协议,在第一个窗口显示在第二个窗口输入的值方法
  2. -( void
    )passValue:(UserEntity *)value
  3. {
  4. self.nameLabel.text = value.userName;
  5. self.ageLabel.text = [NSString stringWithFormat:@ "%d"
    ,value.age];
  6. self.gendarLabel.text = value.gendar;
  7. }

点击Open按钮所触发的事件:

[cpp]view plaincopy

  1. //点击进入第二个窗口的方法
  2. - (IBAction)openBtnClicked:(id)sender {
  3. SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:@ "SecondViewController"
     bundle:[NSBundle mainBundle]];
  4. //设置第二个窗口中的delegate为第一个窗口的self
  5. secondView.delegate = self;
  6. [self.navigationController pushViewController:secondView animated:YES];
  7. }

第二个窗口中声明一个NSObject对象,该对象遵守PassValueDelegate协议:

[cpp]view plaincopy

  1. #import <UIKit/UIKit.h>
  2. #import "PassValueDelegate.h"
  3. @interface SecondViewController : UIViewController
  4. @property (retain, nonatomic) IBOutlet UITextField *nameTextField;
  5. @property (retain, nonatomic) IBOutlet UITextField *ageTextFiled;
  6. @property (retain, nonatomic) IBOutlet UITextField *gendarTextField;
  7. //这里用assign而不用retain是为了防止引起循环引用。
  8. @property(nonatomic,assign) NSObject<PassValueDelegate> *delegate;
  9. - (IBAction)okBtnClicked:(id)sender;
  10. - (IBAction)closeKeyboard:(id)sender;
  11. @end

输入完毕后,点击OK按钮所触发的事件:

[cpp]view plaincopy

  1. - (IBAction)okBtnClicked:(id)sender {
  2. UserEntity *userEntity = [[UserEntity alloc] init];
  3. userEntity.userName = self.nameTextField.text;
  4. userEntity.gendar = self.gendarTextField.text;
  5. userEntity.age = [self.ageTextFiled.text intValue];
  6. //通过委托协议传值
  7. [self.delegate passValue:userEntity];
  8. //退回到第一个窗口
  9. [self.navigationController popViewControllerAnimated:YES];
  10. [userEntity release];
  11. }

以上就实现了使用Delegate在两个ViewController之间传值,这种场景一般应用在进入子界面输入信息,完后要把输入的信息回传给前一个界面的情况,比如修改用户个人信息,点击修改进入修改界面,修改完后到显示界面显示修改后的结果。

4、Block传值                                               //参考 http://liuyafang.blog.51cto.com/8837978/1551399

1.第一页中 声明一个
block,
需要传入一个颜色
,
让当前的
view
变色

//
声明一个 block,
需要传入一个颜色 ,
让当前的 view
变色

void
(^changeColor)( UIColor
*color) = ^( UIColor
*color){

self
. view
. backgroundColor
= color;

};

2
.  第一页中
//block
传值
---------

block
给第二个页面

SecondViewController *secondVC = [[
SecondViewController  
alloc

init
];

//block 传值
--------- 将
block 给第二个页面

secondVC. block
= changeColor;

3.第二页中定义
--

block
变量作为一个类的属性
,
必须要使用
copy
修饰

//block 传值
--------- 将
block 给第二个页面

//block 传值
--- 当
block 变量作为一个类的属性
, 必须要使用
copy 修饰

@property (
nonatomic  , 
copy )
void (^block)(
UIColor
 *color);

4.在第二页中给block传值

//block 传值
--------- 将传值给
block

NSArray
 *array = [
NSArray
 
arrayWithObjects :[
UIColor
 
yellowColor ], [
UIColor
 
cyanColor ], [
UIColor
 
greenColor ], [
UIColor
 
brownColor ], 
nil
];

self
.
block ([array 
objectAtIndex :
rand () % 
4
]);

类和文件

AppDelegate.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

#import "AppDelegate.h"

#import "MainViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Override point for customization after application launch.

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

MainViewController *mainVC = [[MainViewController alloc] init];

UINavigationController *navVc = [[UINavigationController alloc] initWithRootViewController:mainVC];

self.window.rootViewController = navVc;

//模糊效果

navVc.navigationBar.translucent = YES;

[navVc release];

[mainVC release];

[_window release];

return
YES;

}

- (void)dealloc

{

[_window release];

[
super
dealloc];

}

- (void)applicationWillResignActive:(UIApplication *)application

{

// Sent
when the application is about to move from active to inactive state.
This can occur for certain types of temporary interruptions (such as an
incoming phone call or SMS message) or when the user quits the
application and it begins the transition to the background state.

// Use
this method to pause ongoing tasks, disable timers, and throttle down
OpenGL ES frame rates. Games should use this method to pause the game.

}

- (void)applicationDidEnterBackground:(UIApplication *)application

{

// Use
this method to release shared resources, save user data, invalidate
timers, and store enough application state information to restore your
application to its current state in case it is terminated later.

// If your
application supports background execution, this method is called
instead of applicationWillTerminate: when the user quits.

}

- (void)applicationWillEnterForeground:(UIApplication *)application

{

// Called
as part of the transition from the background to the inactive state;
here you can undo many of the changes made on entering the background.

}

- (void)applicationDidBecomeActive:(UIApplication *)application

{

// Restart
any tasks that were paused (or not yet started) while the application
was inactive. If the application was previously in the background,
optionally refresh the user interface.

}

- (void)applicationWillTerminate:(UIApplication *)application

{

// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

}

@end

MainViewController.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

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

#import "MainViewController.h"

#import "SecondViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

self = [
super
initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if
(self) {

// Custom initialization

}

return
self;

}

- (void)viewDidLoad

{

[
super
viewDidLoad];

// Do any additional setup after loading the view.

self.title = @
"block传值"
;

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];

button.frame = CGRectMake(120, 100, 80, 30);

button.backgroundColor = [UIColor magentaColor];

[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

[button setTitle:@
"按钮"
forState:UIControlStateNormal];

button.layer.cornerRadius = 5;

[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

}

- (void)buttonClicked:(UIButton *)button

{

//block语法

//返回值类型 (^block参数名) (参数类型 参数名) = ^返回值类型 (参数类型 参数名) {

//具体实现;

//};

float b = 0;

//1.无参数无返回值

void(^block1)(void) = ^(void){

NSLog(@
"可口可乐"
);

};

//block语法调用

block1();

//2.有参数,无返回值

void(^block2)(NSString *str1, NSString *str2) = ^void(NSString *str1, NSString *str2){

NSString *a = [str1 stringByAppendingString:str2];

NSLog(@
"%@"
, a);

};

block2(@
"abc"
,@
"def"
);

//3.有返回值,无参数

NSString *(^block3)(void) = ^NSString *(void){

return
@
"咿呀咿呀呦"
;

};

NSLog(@
"%@"
,block3());

//4.有参数,有返回值

NSString *(^block4)(NSString *str1) =^NSString *(NSString *str1){

return
[str1 stringByAppendingString:@
"真棒!!!!"
];

};

NSLog(@
"%@"
, block4(@
"苹果电脑"
));

//声明一个block,需要传入一个颜色,让当前的view变色

void(^changeColor)(UIColor *color) = ^(UIColor *color){

self.view.backgroundColor = color;

};

//block传值------------声明一个

void(^changeValue)(UITextField *textField) = ^void(UITextField *textField){

[button setTitle:textField.text forState:UIControlStateNormal];

};

NSLog(@
"%@"
, block1);
//block的地址在全局区

NSLog(@
"%@"
, changeColor);
//如果在block的代码中,使用了block外部的变量,系统会把block指针转移到栈区

SecondViewController *secondVC = [[SecondViewController alloc] init];

//block传值---------将block给第二个页面

secondVC.block = changeColor;

secondVC.blockofValue = changeValue;

secondVC.name = button.currentTitle;

NSLog(@
"%@"
, button.currentTitle);

NSLog(@
"%@"
, secondVC.block);
//使用copy后block会被系统转移到堆区

[self.navigationController pushViewController:secondVC animated:YES];

[secondVC release];

}

- (void)didReceiveMemoryWarning

{

[
super
didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

/*

#pragma mark - Navigation

{

// Get the new view controller using [segue destinationViewController].

// Pass the selected object to the new view controller.

}

*/

@end

SecondViewController.h


1

2

3

4

5

6

7

8

9

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@property (nonatomic , copy)void(^block)(UIColor *color);

@property (nonatomic , copy)void(^blockofValue)(UITextField *textField);

//

@property (nonatomic , copy)NSString *name;

@end

SecondViewController.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

import
"SecondViewController.h"

@interface SecondViewController ()

@property (nonatomic , retain)UITextField *textField;

@end

@implementation SecondViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

self = [
super
initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if
(self) {

// Custom initialization

}

return
self;

}

- (void)viewDidLoad

{

[
super
viewDidLoad];

// Do any additional setup after loading the view.

self.view.backgroundColor = [UIColor whiteColor];

self.textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 220, 30)];

self.textField.borderStyle = UITextBorderStyleRoundedRect;

//

self.textField.text = self.name;

NSLog(@
"%@"
,self.name);

self.textField.clearButtonMode = UITextFieldViewModeAlways;

[self.view addSubview:self.textField];

[_textField release];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 180, 120, 30)];

button.backgroundColor = [UIColor cyanColor];

[button setTitle:@
"点击"
forState:UIControlStateNormal];

button.layer.cornerRadius = 5;

[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

}

- (void)buttonClicked:(UIButton *)button

{

//block传值---------将传值给block

NSArray
*array = [NSArray arrayWithObjects:[UIColor yellowColor], [UIColor
cyanColor], [UIColor greenColor], [UIColor brownColor], nil];

self.block([array objectAtIndex:rand() % 4]);

//block传值---------将传值给block

self.blockofValue(self.textField);

[self.navigationController popToRootViewControllerAnimated:YES];

}

- (void)didReceiveMemoryWarning

{

[
super
didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

/*

#pragma mark - Navigation

{

// Get the new view controller using [segue destinationViewController].

// Pass the selected object to the new view controller.

}

*/

@end

5

单例

传值

单例只会对某个类实例化一次/单例类,对单例这个类实例化一次有且仅有一个对象

你单例初始化,只能初始化一次,然后你指向的对象,其实都是指向一个内存地址,也就是同一块内存,所以都是一样的/

那么,只能有一个对象,就是实例化的那个

(1)定义单例类singleton      .h文件

#import <Foundation/Foundation.h>

@interface singleton : NSObject  //步骤一

//@property (strong,nonatomic) UITextField *value;//最开始的时候把这个value定义为UITextField了,然后在init里面又没有初始化它,就取不到值。任何对象都要初始化它才能使用。

@property (strong, nonatomic) NSString *value;

//+(id)shareData:

+(singleton *)shareData;  //步骤二

@end

//.m文件

#import "singleton.h"

@implementation singleton

static
singleton *singletonData = nil;  //步骤三

+(singleton *)shareData {  //步骤四

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

singletonData = [[singleton alloc] init];

});

return singletonData;

}

-(id)init {  //步骤五

if (self = [super init]) {

//        self.value = [[UITextField alloc]init];

}

return self;

}

@end

//以上是一个完整单例子

(2)ViewController

#import <UIKit/UIKit.h>

#import "OneViewController.h"

#import "singleton.h"  
//引用单例

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *qqTextfield;

- (IBAction)go:(id)sender;

@end

- (IBAction)go:(id)sender {

//单例的使用

singleton *oneS = [singleton shareData];

//    oneS.value.text = self.qqTextfield.text;

oneS.value = self.qqTextfield.text;

OneViewController *oneVC = [[OneViewController alloc]init];

[self presentViewController:oneVC animated:YES completion:nil];

}

(3)OneViewController

#import <UIKit/UIKit.h>

#import "singleton.h"

@interface OneViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *oneTextField;

@end

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view from its nib.

self.oneTextField.text = [singleton shareData].value;

}

6:数据共享。

OS app之间要共享数据不是那么容易,因为每个app都是sandbox。然后,有时候又不得不跟其它app之间共享数据,那应该怎么办呢?

下面是一些常用方法的总结:

  • UIDocumentInteractionController

    Availability: iOS 3.2+

    具体用法参见: http://mobile.tutsplus.com/tutorials/iphone/previewing-and-opening-documents-with-uidocumentinteractioncontroller/

  • UIActivityViewController 
    Availability: iOS 6.0+
  • Shared Keychain Access
    这个要求app之间用的是同样的证书
  • Custom URL Scheme
    通过构造URL,把数据作为参数传递过去。 本地测试过,传递10000个字符都可以,不过不要太长,内存可能吃不消。
  • Web Service 通过dropbox或者其他第三方的服务来共享数据。
  • UIPasteboard + URL Scheme 通过URL scheme传递UIPasteboard的名称,然后通过UIPasteboard共享数据。
    微信iOS SDK应该采用的就是这种方式。
    不过在iOS 7上,这种方法会存在问题,如果采用这种方案,得赶紧想办法解决。

1)  http://enharmonichq.com/sharing-data-locally-between-ios-apps/

2)  http://stackoverflow.com/questions/17080074/ios7-beta-doesnt-allow-inter-app-communication-by-uipasteboard

7:通知传值

通知中心
NSNotificationCenter提供了一种更加解耦的方式。最典型的应用就是任何对象对可以发送通知到中心,同时任何对象可以监听中心的通知。
发送通知的代码如下:

[[NSNotificationCenter defaultCenter] postNotificationName:@”myNotificationName” object:broadcasterObject];
注册接收通知的代码如下:

[[NSNotificationCenter
defaultCenter] addObserver:listenerObject selector:@selector(receivingMethodOnListener:) name:@”myNotificationName” object:nil];

注册通知的时候可以指定一个具体的广播者对象,但这不是必须的。你可能注意到了defaultCenter 。实际上这是你在应用中会使用到的唯一的中心。通知会向整个应用开放,因此只有一个中心。
同时还有一个NSDistributedNotificationCenter。这是用来应用间通信的。在整个计算机上只有一个该类型的中心。
优点: 通知的发送者和接受者都不需要知道对方。可以指定接收通知的具体方法。通知名可以是任何字符串。
缺点: 较键值观察需要多点代码。在删掉前必须移除监听者。 不能传大量数值,只能让谁去做什么事。

时间: 2024-09-27 02:02:28

工作记录8:iOS 传值问题总结(7种传值完美介绍)的相关文章

[工作记录] Android OpenGL ES 2.0: square texture not supported on some device

npot texture: non-power-of-two texture.rectangle texture: non-square (height != wdith) 在测试Samsumg Galaxy S4的时候, 发现rectangle texture支持不好, 虽然创建成功, 但是绘制有问题. 不同的模块出现类似的情况: 纹理采样出的颜色是(0,0,0,1). 在排除了所有可能的runtime问题以后, 尝试性改了纹理格式无果, 又尝试性的改了下尺寸, 竟然好了. 我擦... 而Ga

iOS的四种传值方式

传值有四种方法 : 1.属性传值 2.单例传值 3.代理传值 4.block传值 一.属性传值   (前-->后) 1. 后面的界面定义一个属性  存放前一个界面传过来的值 注意:属性定义成字符串还是别的类型 取决于你的需求 2. 后面的界面创建完毕后,为属性赋值(记录需要传递的值) 3. 在需要使用值的地方  使用属性记录的值 4. 通过 定义属性 达到传值目的的方法 称为属性传值 属性传值一般用于 从前一个界面向后一个界面传值 二.单例传值  (万能的传值方式  可以跨多个页面之间进行传值)

工作记录

 20140428  6 20140505 9 20140512 4 20140519 11 20140526 8  20140429  5 20140506 10 20140513 6 20140520 10 20140527 11  20140430  6 20140507 14 20140514 7 20140521 10 20140528 9 20140501 6 20140508 4 20140515 9 20140522 10 20140529 11 20140502 5 20140

[工作记录] Android OpenSL ES: references &amp; AAC related

AAC V.S. MP3 http://en.wikipedia.org/wiki/Advanced_Audio_Coding#AAC.27s_improvements_over_MP3 AAC patent lisense FAQ: http://www.vialicensing.com/licensing/aac-faq.aspx you may need a license but usually no fees, exept that when end user products are

[工作记录] Android OpenGL ES: non-square texture - continue

previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found that it is the mipmap of a non-square texture that cause the black texture problem: http://stackoverflow.com/questions/5052762/using-mipmaps-results-

工作记录 - OBB的解决方案

之前关于OBB的内容: Android上使用native IO 最近工作中的问题笔记 工作记录[续] android OBB 自从用了Java来mount OBB, 再也没有遇到挂载的问题. 但最近在LG Nexus5 和LG G2上测试, 发现某个大约30K文件的文件, 一次性读取出来以后, 处理会报错. 最后排除各种因素, 比如为了排除buffer坏掉的因素,读的时候单独new一个新buffer,一次性读取,然后dump到sd卡.对比dump出的文件, 发现整个文件中间有n个字节(大约是32

【工作记录】c#操作win7注册表

这里讲一 C# 小列子(高手请绕过此地! ), 我们平时都是在xp开发比较多...不过现在很多开发人员也在win7下开发了. 下面是在 LocalMachine 下的 一下注册表操作 ,就不详说了 private static void DeleteRegistry(string name){string[] aimnames;RegistryKey hkml = Registry.LocalMachine;RegistryKey software = hkml.OpenSubKey("SOFT

深入了解iOS中的VC切换的传值方式

由于上次面试中有提到相关内容,所以这次我专门深入研究了iOS的几种方式: 首先把所有的传值方式都列出来,如果有遗漏,请指正 首先列出iOS中使用的传值方式: init 传值(即在创建VC的时候就对响应的参数进行设置) property 传值(即属性赋值) Router 传值(这个在OC中被使用,因为作者没有写Swift版本,所以先开个坑,估计我会填坑) Delegate 传值(通过协议和代理传值) 闭包(block)传值 (通过swift中的闭包,类似于OC中的block传值) Notifica

201404-20151119工作记录

20140417-20151119 工作记录 =======================改科室BUG20140416 入职2014041720140418 下午忘了打卡 周五======================= =======================2014042120140422201404232014042420140425======================== ========================材料分析 20140428201404292014