├── AZXTallyBook.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── azx.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── azx.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── AZXTallyBook.xcscheme │ └── xcschememanagement.plist ├── AZXTallyBook.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── azx.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── AZXTallyBook ├── AZXAccountTableViewCell.h ├── AZXAccountTableViewCell.m ├── AZXAccountViewController.h ├── AZXAccountViewController.m ├── AZXAddTypeCollectionViewCell.h ├── AZXAddTypeCollectionViewCell.m ├── AZXAddTypeViewController.h ├── AZXAddTypeViewController.m ├── AZXAllHistoryTableViewCell.h ├── AZXAllHistoryTableViewCell.m ├── AZXAllHistoryViewController.h ├── AZXAllHistoryViewController.m ├── AZXMonthHIstoryViewController.h ├── AZXMonthHIstoryViewController.m ├── AZXNewAccountTableViewController.h ├── AZXNewAccountTableViewController.m ├── AZXOperateTypeTableViewCell.h ├── AZXOperateTypeTableViewCell.m ├── AZXOperateTypeTableViewController.h ├── AZXOperateTypeTableViewController.m ├── AZXPieTableViewCell.h ├── AZXPieTableViewCell.m ├── AZXPieView.h ├── AZXPieView.m ├── AZXPieViewController.h ├── AZXPieViewController.m ├── AZXSettingTableViewController.h ├── AZXSettingTableViewController.m ├── AZXTallyBook.xcdatamodeld │ ├── .xccurrentversion │ └── AZXTallyBook.xcdatamodel │ │ └── contents ├── AZXTypeDetailViewController.h ├── AZXTypeDetailViewController.m ├── Account+CoreDataProperties.h ├── Account+CoreDataProperties.m ├── Account.h ├── Account.m ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── iconiPadApp_76pt.png │ │ ├── iconiPadApp_76pt@2x.png │ │ ├── iconiPadProApp_83.5pt@2x.png │ │ ├── iconiPadSpootlight5_29pt.png │ │ ├── iconiPadSpootlight5_29pt@2x.png │ │ ├── iconiPadSpootlight7_40pt.png │ │ ├── iconiPadSpootlight7_40pt@2x.png │ │ ├── iconiPhoneApp_60pt@2x.png │ │ ├── iconiPhoneApp_60pt@3x.png │ │ ├── iconiPhoneSpootlight5_29pt@2x.png │ │ ├── iconiPhoneSpootlight5_29pt@3x.png │ │ ├── iconiPhoneSpootlight7_40pt@2x.png │ │ └── iconiPhoneSpootlight7_40pt@3x.png │ ├── Contents.json │ ├── 类别 │ │ ├── Contents.json │ │ ├── 交通路费.imageset │ │ │ ├── Contents.json │ │ │ ├── 交通路费.png │ │ │ ├── 交通路费@2x.png │ │ │ └── 交通路费@3x.png │ │ ├── 其他支出.imageset │ │ │ ├── Contents.json │ │ │ ├── 其他支出.png │ │ │ ├── 其他支出@2x.png │ │ │ └── 其他支出@3x.png │ │ ├── 其他收入.imageset │ │ │ ├── Contents.json │ │ │ ├── 其他收入.png │ │ │ ├── 其他收入@2x.png │ │ │ └── 其他收入@3x.png │ │ ├── 化妆护理.imageset │ │ │ ├── Contents.json │ │ │ ├── 化妆护理.png │ │ │ ├── 化妆护理@2x.png │ │ │ └── 化妆护理@3x.png │ │ ├── 医疗体检.imageset │ │ │ ├── Contents.json │ │ │ ├── 医疗体检.png │ │ │ ├── 医疗体检@2x.png │ │ │ └── 医疗体检@3x.png │ │ ├── 外出旅游.imageset │ │ │ ├── Contents.json │ │ │ ├── 外出旅游.png │ │ │ ├── 外出旅游@2x.png │ │ │ └── 外出旅游@3x.png │ │ ├── 奖金福利.imageset │ │ │ ├── Contents.json │ │ │ ├── 奖金福利.png │ │ │ ├── 奖金福利@2x.png │ │ │ └── 奖金福利@3x.png │ │ ├── 学习教育.imageset │ │ │ ├── Contents.json │ │ │ ├── 学习教育.png │ │ │ ├── 学习教育@2x.png │ │ │ └── 学习教育@3x.png │ │ ├── 工资薪酬.imageset │ │ │ ├── Contents.json │ │ │ ├── 工资薪酬.png │ │ │ ├── 工资薪酬@2x.png │ │ │ └── 工资薪酬@3x.png │ │ ├── 彩票中奖.imageset │ │ │ ├── Contents.json │ │ │ ├── 彩票中奖.png │ │ │ ├── 彩票中奖@2x.png │ │ │ └── 彩票中奖@3x.png │ │ ├── 慈善捐赠.imageset │ │ │ ├── Contents.json │ │ │ ├── 慈善捐赠.png │ │ │ ├── 慈善捐赠@2x.png │ │ │ └── 慈善捐赠@3x.png │ │ ├── 房租水电.imageset │ │ │ ├── Contents.json │ │ │ ├── 房租水电.png │ │ │ ├── 房租水电@2x.png │ │ │ └── 房租水电@3x.png │ │ ├── 投资理财.imageset │ │ │ ├── Contents.json │ │ │ ├── 投资理财.png │ │ │ ├── 投资理财@2x.png │ │ │ └── 投资理财@3x.png │ │ ├── 日常用品.imageset │ │ │ ├── Contents.json │ │ │ ├── 日常用品.png │ │ │ ├── 日常用品@2x.png │ │ │ └── 日常用品@3x.png │ │ ├── 服装首饰.imageset │ │ │ ├── Contents.json │ │ │ ├── 服装首饰.png │ │ │ ├── 服装首饰@2x.png │ │ │ └── 服装首饰@3x.png │ │ ├── 油费维护.imageset │ │ │ ├── Contents.json │ │ │ ├── 油费维护.png │ │ │ ├── 油费维护@2x.png │ │ │ └── 油费维护@3x.png │ │ ├── 游戏娱乐.imageset │ │ │ ├── Contents.json │ │ │ ├── 游戏娱乐.png │ │ │ ├── 游戏娱乐@2x.png │ │ │ └── 游戏娱乐@3x.png │ │ ├── 烟酒消费.imageset │ │ │ ├── Contents.json │ │ │ ├── 烟酒消费.png │ │ │ ├── 烟酒消费@2x.png │ │ │ └── 烟酒消费@3x.png │ │ ├── 生意经营.imageset │ │ │ ├── Contents.json │ │ │ ├── 生意经营.png │ │ │ ├── 生意经营@2x.png │ │ │ └── 生意经营@3x.png │ │ ├── 电子产品.imageset │ │ │ ├── Contents.json │ │ │ ├── 电子产品.png │ │ │ ├── 电子产品@2x.png │ │ │ └── 电子产品@3x.png │ │ ├── 网上购物.imageset │ │ │ ├── Contents.json │ │ │ ├── 网上购物.png │ │ │ ├── 网上购物@2x.png │ │ │ └── 网上购物@3x.png │ │ ├── 运动健身.imageset │ │ │ ├── Contents.json │ │ │ ├── 运动健身.png │ │ │ ├── 运动健身@2x.png │ │ │ └── 运动健身@3x.png │ │ ├── 银行利息.imageset │ │ │ ├── Contents.json │ │ │ ├── 银行利息.png │ │ │ ├── 银行利息@2x.png │ │ │ └── 银行利息@3x.png │ │ └── 餐饮食品.imageset │ │ │ ├── Contents.json │ │ │ ├── 餐饮食品.png │ │ │ ├── 餐饮食品@2x.png │ │ │ └── 餐饮食品@3x.png │ └── 系统图标 │ │ ├── Contents.json │ │ ├── 统计.imageset │ │ ├── Contents.json │ │ ├── 统计25pt.png │ │ ├── 统计25pt@2x.png │ │ └── 统计25pt@3x.png │ │ ├── 记账.imageset │ │ ├── Contents.json │ │ ├── 记账25pt.png │ │ ├── 记账25pt@2x.png │ │ └── 记账25pt@3x.png │ │ ├── 设置.imageset │ │ ├── Contents.json │ │ ├── 设置25pt.png │ │ ├── 设置25pt@2x.png │ │ └── 设置25pt@3x.png │ │ └── 账本.imageset │ │ ├── Contents.json │ │ ├── 账本25pt.png │ │ ├── 账本25pt@2x.png │ │ └── 账本25pt@3x.png ├── Base.lproj │ └── LaunchScreen.storyboard ├── Info.plist ├── Main.storyboard ├── UIViewController+BackButtonHandler.h ├── UIViewController+BackButtonHandler.m └── main.m ├── AZXTallyBookTests ├── AZXTallyBookTests.m └── Info.plist ├── AZXTallyBookUITests ├── AZXTallyBookUITests.m └── Info.plist ├── Podfile ├── Podfile.lock ├── Pods ├── Headers │ ├── Private │ │ └── VENCalculatorInputView │ │ │ ├── NSString+VENCalculatorInputView.h │ │ │ ├── UITextField+VENCalculatorInputView.h │ │ │ ├── VENCalculatorInputTextField.h │ │ │ ├── VENCalculatorInputView.h │ │ │ └── VENMoneyCalculator.h │ └── Public │ │ └── VENCalculatorInputView │ │ ├── NSString+VENCalculatorInputView.h │ │ ├── UITextField+VENCalculatorInputView.h │ │ ├── VENCalculatorInputTextField.h │ │ ├── VENCalculatorInputView.h │ │ └── VENMoneyCalculator.h ├── Manifest.lock ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── azx.xcuserdatad │ │ └── xcschemes │ │ ├── Pods.xcscheme │ │ ├── VENCalculatorInputView.xcscheme │ │ └── xcschememanagement.plist ├── Target Support Files │ ├── Pods │ │ ├── Pods-acknowledgements.markdown │ │ ├── Pods-acknowledgements.plist │ │ ├── Pods-dummy.m │ │ ├── Pods-frameworks.sh │ │ ├── Pods-resources.sh │ │ ├── Pods.debug.xcconfig │ │ └── Pods.release.xcconfig │ └── VENCalculatorInputView │ │ ├── VENCalculatorInputView-dummy.m │ │ ├── VENCalculatorInputView-prefix.pch │ │ └── VENCalculatorInputView.xcconfig └── VENCalculatorInputView │ ├── LICENSE │ ├── README.md │ └── VENCalculatorInputView │ ├── Images │ ├── VENCalculatorIconBackspace.png │ └── VENCalculatorIconBackspace@2x.png │ ├── NSString+VENCalculatorInputView.h │ ├── NSString+VENCalculatorInputView.m │ ├── UITextField+VENCalculatorInputView.h │ ├── UITextField+VENCalculatorInputView.m │ ├── VENCalculatorInputTextField.h │ ├── VENCalculatorInputTextField.m │ ├── VENCalculatorInputView.h │ ├── VENCalculatorInputView.m │ ├── VENCalculatorInputView.xib │ ├── VENMoneyCalculator.h │ └── VENMoneyCalculator.m ├── README.md └── screenshots ├── 4.7_1.png ├── 4.7_2.png └── 4.7_3.png /AZXTallyBook.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AZXTallyBook.xcodeproj/project.xcworkspace/xcuserdata/azx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook.xcodeproj/project.xcworkspace/xcuserdata/azx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AZXTallyBook.xcodeproj/xcuserdata/azx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /AZXTallyBook.xcodeproj/xcuserdata/azx.xcuserdatad/xcschemes/AZXTallyBook.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AZXTallyBook.xcodeproj/xcuserdata/azx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AZXTallyBook.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7F057DA41C8D6B28003DA3C7 16 | 17 | primary 18 | 19 | 20 | 7F057DC01C8D6B28003DA3C7 21 | 22 | primary 23 | 24 | 25 | 7F057DCB1C8D6B28003DA3C7 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AZXTallyBook.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AZXTallyBook.xcworkspace/xcuserdata/azx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook.xcworkspace/xcuserdata/azx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AZXTallyBook.xcworkspace/xcuserdata/azx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAccountTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAccountTableViewCell.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXAccountTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *typeImage; // 图像显示名称为typeName的图片 14 | @property (weak, nonatomic) IBOutlet UILabel *typeName; 15 | @property (weak, nonatomic) IBOutlet UILabel *money; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAccountTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAccountTableViewCell.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXAccountTableViewCell.h" 10 | 11 | @implementation AZXAccountTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAccountViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAccountViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/2/21. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | // 这个Controller有两个不同的UI(有按钮、无按钮) 10 | 11 | #import 12 | 13 | @interface AZXAccountViewController : UIViewController 14 | 15 | @property (nonatomic, strong) NSString *passedDate; // 从别处传来的date值,用做Predicate筛选Fetch的ManagedObject 16 | 17 | @property (nonatomic, strong) NSString *selectedType; // 若从统计的类别处传来,则一进入界面就选中该类型的行 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAddTypeCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAddTypeCollectionViewCell.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/16. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXAddTypeCollectionViewCell : UICollectionViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *image; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAddTypeCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAddTypeCollectionViewCell.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/16. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXAddTypeCollectionViewCell.h" 10 | 11 | @implementation AZXAddTypeCollectionViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAddTypeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAddTypeViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/16. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXAddTypeViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAddTypeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAddTypeViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/16. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXAddTypeViewController.h" 10 | #import "AZXAddTypeCollectionViewCell.h" 11 | #import "UIViewController+BackButtonHandler.h" 12 | 13 | @interface AZXAddTypeViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet UICollectionView *typeCollectionView; 16 | 17 | @property (weak, nonatomic) IBOutlet UIImageView *showImage; 18 | 19 | @property (weak, nonatomic) IBOutlet UITextField *typeTextField; 20 | 21 | @property (strong, nonatomic) NSMutableArray *typeArray; // 存放各种类别名称(用来显示collectionView中图片的数据源) 22 | 23 | @property (strong, nonatomic) NSUserDefaults *defaults; 24 | 25 | @property (strong, nonatomic) NSString *incomeType; 26 | 27 | @property (strong, nonatomic) NSMutableArray *incomeArray; // 收入类别数组 28 | 29 | @property (strong, nonatomic) NSMutableArray *expenseArray; // 支出类别数组 30 | 31 | @property (strong, nonatomic) UIView *shadowView; // 实现点击空白区域返回键盘的隔层 32 | 33 | @property (weak, nonatomic) IBOutlet UIButton *localPhotoButton; // 打开本地相册 34 | 35 | @property (strong, nonatomic) UIImage *selectedPhoto; // 从相册里选择的图片 36 | 37 | @property (strong, nonatomic) NSIndexPath *selectedIndexOfImage; // 选中的屏幕上的图片 38 | 39 | @property (assign, nonatomic) BOOL isFromAlbum; // 最后保存时是从相册选择的还是从已有的图片选择,YES代表从相册里选择 40 | @end 41 | 42 | @implementation AZXAddTypeViewController 43 | - (NSString *)incomeType { 44 | if (!_incomeType) { 45 | _incomeType = @"expense"; // 收支类型默认为支出 46 | } 47 | return _incomeType; 48 | } 49 | 50 | - (IBAction)typeChanged:(UISegmentedControl *)sender { 51 | if (sender.selectedSegmentIndex == 0) { 52 | self.incomeType = @"expense"; 53 | } else { 54 | self.incomeType = @"income"; 55 | } 56 | } 57 | 58 | // 打开相册 59 | - (IBAction)localPhoto:(UIButton *)sender { 60 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { 61 | // 如果相册可用 62 | UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init]; 63 | photoPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 64 | photoPicker.delegate = self; 65 | //设置选择后的图片可被编辑 66 | photoPicker.allowsEditing = YES; 67 | 68 | // 设置其弹出方式(自动适配iPad和iPhone) 69 | photoPicker.modalPresentationStyle = UIModalPresentationPopover; 70 | 71 | [self presentViewController:photoPicker animated:YES completion:nil]; 72 | 73 | // 获取popoverPresentationController 74 | UIPopoverPresentationController *presentationController = [photoPicker popoverPresentationController]; 75 | 76 | presentationController.permittedArrowDirections = UIPopoverArrowDirectionAny; 77 | presentationController.sourceView = self.localPhotoButton; 78 | presentationController.sourceRect = self.localPhotoButton.bounds; 79 | } 80 | } 81 | 82 | 83 | - (void)viewDidLoad { 84 | [super viewDidLoad]; 85 | 86 | self.typeCollectionView.delegate = self; 87 | self.typeCollectionView.dataSource = self; 88 | self.typeTextField.delegate = self; 89 | 90 | self.typeCollectionView.backgroundColor = [UIColor whiteColor]; 91 | 92 | self.defaults = [NSUserDefaults standardUserDefaults]; 93 | 94 | // 一进入界面就弹出键盘 95 | [self.typeTextField becomeFirstResponder]; 96 | 97 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"保存" style:UIBarButtonItemStyleDone target:self action:@selector(rightBarItemPressed)]; 98 | } 99 | 100 | - (void)viewWillAppear:(BOOL)animated { 101 | [super viewWillAppear:animated]; 102 | 103 | // 取得支出收入的所有类型 104 | self.expenseArray = [NSMutableArray arrayWithArray:[self.defaults objectForKey:@"expenseAZX"]]; 105 | self.incomeArray = [NSMutableArray arrayWithArray:[self.defaults objectForKey:@"incomeAZX"]]; 106 | 107 | if (![self.defaults objectForKey:@"imagesShowInAZXAddTypeViewController"]) { 108 | // 如果还未保存显示在这界面的图片数组 109 | self.typeArray = [NSMutableArray arrayWithArray:@[@"餐饮食品", @"交通路费", @"日常用品", @"服装首饰", @"学习教育", @"烟酒消费", @"房租水电", @"网上购物", @"运动健身", @"电子产品", @"化妆护理", @"医疗体检", @"游戏娱乐", @"外出旅游", @"油费维护", @"慈善捐赠", @"其他支出", @"工资薪酬", @"奖金福利", @"生意经营", @"投资理财", @"彩票中奖", @"银行利息", @"其他收入"]]; 110 | [self.defaults setObject:self.typeArray forKey:@"imagesShowInAZXAddTypeViewController"]; 111 | } else { 112 | self.typeArray = [NSMutableArray arrayWithArray:[self.defaults objectForKey:@"imagesShowInAZXAddTypeViewController"]]; 113 | } 114 | } 115 | 116 | - (void)rightBarItemPressed { 117 | // 首先判断是否新类别名已存在,不允许重复 118 | if ([self.expenseArray containsObject:self.typeTextField.text] || [self.incomeArray containsObject:self.typeTextField.text]) { 119 | [self popoverAlertControllerWithMessage:@"类别名已存在,请使用新的类别名"]; 120 | } else if (self.typeTextField.text && self.showImage.image) { 121 | // 若两者都已输入,将图片与类别名保存并联系起来 122 | [self savePhotoWithTypeName]; 123 | 124 | // 跳回上一界面 125 | [self.navigationController popViewControllerAnimated:YES]; 126 | } else { 127 | // 弹出提示 128 | [self popoverAlertControllerWithMessage:@"图片与类别名都需要输入"]; 129 | } 130 | } 131 | 132 | - (void)popoverAlertControllerWithMessage:(NSString *)message { 133 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert]; 134 | 135 | UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil]; 136 | 137 | [alert addAction:cancel]; 138 | 139 | [self presentViewController:alert animated:YES completion:nil]; 140 | } 141 | 142 | // 点击back按钮后调用 引用的他人写的一个extension 143 | - (BOOL)navigationShouldPopOnBackButton { 144 | if (![self.typeTextField.text isEqualToString:@""] && self.showImage.image) { 145 | // 当二者都填上内容时,点击返回询问是否保存 146 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"还未保存,是否返回?" preferredStyle:UIAlertControllerStyleAlert]; 147 | 148 | UIAlertAction *OK = [UIAlertAction actionWithTitle:@"返回" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 149 | [self.navigationController popViewControllerAnimated:YES]; 150 | }]; 151 | 152 | UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 153 | 154 | [alert addAction:cancel]; 155 | [alert addAction:OK]; 156 | 157 | [self presentViewController:alert animated:YES completion:nil]; 158 | 159 | return NO; 160 | } 161 | return YES; 162 | } 163 | 164 | // 将图片与类别名关联并保存 165 | - (void)savePhotoWithTypeName { 166 | if (self.isFromAlbum) { 167 | // 如果是从相册中选择的 168 | [self savePhotoFromAlbum]; 169 | } else { 170 | // 如果是从已有的图片中选择的 171 | NSInteger index = [self.typeCollectionView indexPathsForSelectedItems][0].row; 172 | // 图片的名称(路径) 173 | NSString *imageName = self.typeArray[index]; 174 | // 将二者关联起来 175 | [self.defaults setObject:imageName forKey:self.typeTextField.text]; 176 | } 177 | } 178 | 179 | - (void)savePhotoFromAlbum { 180 | NSData *data; 181 | if (UIImagePNGRepresentation(self.selectedPhoto) == nil) { 182 | data = UIImageJPEGRepresentation(self.selectedPhoto, 1.0); 183 | } 184 | else { 185 | data = UIImagePNGRepresentation(self.selectedPhoto); 186 | } 187 | 188 | //图片保存的路径 189 | //这里将图片放在沙盒的documents文件夹中 190 | NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; 191 | 192 | //文件管理器 193 | NSFileManager *fileManager = [NSFileManager defaultManager]; 194 | 195 | // 新类别名 196 | NSString *type = self.typeTextField.text; 197 | 198 | //把刚刚图片转换的data对象拷贝至沙盒中 并保存为 类别名.png 199 | [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil]; 200 | [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:[NSString stringWithFormat:@"/%@.png", type]] contents:data attributes:nil]; 201 | 202 | //得到选择后沙盒中图片的完整路径 203 | NSString *filePath = [[NSString alloc]initWithFormat:@"%@%@",DocumentsPath, [NSString stringWithFormat:@"/%@.png", type]]; 204 | 205 | 206 | // 将类别名与图片的储存路径关联起来,到时候取出图片时直接用[imageNamed:储存路径]方法 207 | [self.defaults setObject:filePath forKey:type]; 208 | 209 | // 将类别名加入相应的类别数组 210 | if ([self.incomeType isEqualToString:@"income"]) { 211 | [self.incomeArray addObject:type]; 212 | [self.defaults setObject:self.incomeArray forKey:@"incomeAZX"]; 213 | } else { 214 | [self.expenseArray addObject:type]; 215 | [self.defaults setObject:self.expenseArray forKey:@"expenseAZX"]; 216 | } 217 | 218 | // 并将新加入的图片保存在此页面的typeArray,下次进入界面就会显示出来 219 | [self.typeArray addObject:filePath]; 220 | [self.defaults setObject:self.typeArray forKey:@"imagesShowInAZXAddTypeViewController"]; 221 | } 222 | 223 | #pragma mark - textField delegate methods 224 | 225 | - (void)textFieldDidBeginEditing:(UITextField *)textField { 226 | //插入一个透明的夹层 227 | [self insertTransparentView]; 228 | [self.shadowView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textFieldResignKeyboard)]]; 229 | } 230 | 231 | - (void)insertTransparentView { 232 | self.shadowView = [[UIView alloc] initWithFrame:self.view.frame]; 233 | [self.view addSubview:self.shadowView]; 234 | [self.view bringSubviewToFront:self.shadowView]; 235 | } 236 | 237 | - (void)textFieldResignKeyboard { 238 | [self.typeTextField resignFirstResponder]; 239 | [self.shadowView removeFromSuperview]; 240 | self.shadowView = nil; 241 | } 242 | 243 | 244 | 245 | #pragma mark - UICollectionViewDataSource 246 | 247 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 248 | return 1; 249 | } 250 | 251 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 252 | return self.typeArray.count; 253 | } 254 | 255 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 256 | AZXAddTypeCollectionViewCell *cell = [self.typeCollectionView dequeueReusableCellWithReuseIdentifier:@"typeImageCell" forIndexPath:indexPath]; 257 | // 得到相应名称(路径)的图片, 258 | cell.image.image = [UIImage imageNamed:self.typeArray[indexPath.row]]; 259 | UIView *backgroundView = [[UIView alloc] initWithFrame:cell.frame]; 260 | backgroundView.backgroundColor = [UIColor lightGrayColor]; 261 | 262 | cell.selectedBackgroundView = backgroundView; 263 | 264 | return cell; 265 | } 266 | 267 | 268 | #pragma mark - UICollectionViewDelegate 269 | 270 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 271 | AZXAddTypeCollectionViewCell *cell = (AZXAddTypeCollectionViewCell *)[self.typeCollectionView cellForItemAtIndexPath:indexPath]; 272 | 273 | // 显示选中的图片 274 | self.showImage.image = cell.image.image; 275 | 276 | // 设为从已有图片选择 277 | self.isFromAlbum = NO; 278 | } 279 | 280 | 281 | #pragma mark - UICollectionViewDelegateFlowLayout 282 | 283 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 284 | CGFloat totalWidth = self.typeCollectionView.frame.size.width; 285 | 286 | // 一行显示4个cell 287 | return CGSizeMake(totalWidth / 4 , totalWidth / 4); 288 | } 289 | 290 | #pragma mark - UIImagePickerControllerDelegate 291 | 292 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 293 | [picker dismissViewControllerAnimated:YES completion:^ { 294 | // 如果之前屏幕上有选中的图片,将屏幕上被选中的cell给deselect掉 295 | if ([self.typeCollectionView indexPathsForSelectedItems].count != 0) { 296 | [self.typeCollectionView deselectItemAtIndexPath:[self.typeCollectionView indexPathsForSelectedItems][0] animated:YES]; 297 | } 298 | }]; 299 | 300 | NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; 301 | 302 | if ([type isEqualToString:@"public.image"]) { 303 | // 当选择的类型是图片时,显示在小imageView上 304 | self.selectedPhoto = [info objectForKey:@"UIImagePickerControllerEditedImage"]; 305 | 306 | self.showImage.image = self.selectedPhoto; 307 | } 308 | 309 | // 设为从相册选择 310 | self.isFromAlbum = YES; 311 | } 312 | 313 | - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { 314 | [picker dismissViewControllerAnimated:YES completion:nil]; 315 | } 316 | 317 | /* 318 | #pragma mark - Navigation 319 | 320 | // In a storyboard-based application, you will often want to do a little preparation before navigation 321 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 322 | // Get the new view controller using [segue destinationViewController]. 323 | // Pass the selected object to the new view controller. 324 | } 325 | */ 326 | 327 | @end 328 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAllHistoryTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAllHistoryTableViewCell.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXAllHistoryTableViewCell : UITableViewCell 12 | @property (weak, nonatomic) IBOutlet UILabel *date; 13 | @property (weak, nonatomic) IBOutlet UILabel *money; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAllHistoryTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAllHistoryTableViewCell.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXAllHistoryTableViewCell.h" 10 | 11 | @implementation AZXAllHistoryTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAllHistoryViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAllHistoryViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXAllHistoryViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXAllHistoryViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXAllHistoryViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXAllHistoryViewController.h" 10 | #import 11 | #import "AppDelegate.h" 12 | #import "Account.h" 13 | #import "AZXAllHistoryTableViewCell.h" 14 | #import "AZXMonthHIstoryViewController.h" 15 | 16 | @interface AZXAllHistoryViewController () 17 | @property (weak, nonatomic) IBOutlet UILabel *totalDetailLabel; 18 | 19 | @property (weak, nonatomic) IBOutlet UILabel *remainMoneyLabel; 20 | 21 | @property (weak, nonatomic) IBOutlet UITableView *monthTableView; 22 | 23 | @property (strong, nonatomic) NSArray *dataArray; // 储存fetch来的所有Account 24 | 25 | @property (strong, nonatomic) NSMutableArray *monthIncome; // 每个月的收入金额 26 | 27 | @property (strong, nonatomic) NSMutableArray *monthExpense; // 每个月的支出金额 28 | 29 | @property (assign, nonatomic) double totalIncome; // 总收入 30 | 31 | @property (assign, nonatomic) double totalExpense; // 总支出 32 | 33 | @property (strong, nonatomic) NSMutableArray *uniqueDateArray; // 储存不重复月份的数组 34 | 35 | @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 36 | @end 37 | 38 | @implementation AZXAllHistoryViewController 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | // Do any additional setup after loading the view. 43 | 44 | self.monthTableView.dataSource = self; 45 | 46 | AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 47 | self.managedObjectContext = appDelegate.managedObjectContext; 48 | 49 | // 数组的初始化 50 | self.monthIncome = [NSMutableArray array]; 51 | self.monthExpense = [NSMutableArray array]; 52 | 53 | [self judgeFirstLoadThisView]; 54 | } 55 | 56 | - (void)judgeFirstLoadThisView { 57 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 58 | 59 | if (![defaults boolForKey:@"haveLoadedAZXAllHistoryViewController"]) { 60 | // 第一次进入此页面 61 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"教程" message:@"首页显示所有月份的账单总额,点击相应月份查看该月份所有天数的详细内容,手指左滑可删除相应行的记录" preferredStyle:UIAlertControllerStyleAlert]; 62 | 63 | UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"知道了,不再提醒" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 64 | [defaults setBool:YES forKey:@"haveLoadedAZXAllHistoryViewController"]; 65 | }]; 66 | 67 | [alert addAction:actionOK]; 68 | 69 | [self presentViewController:alert animated:YES completion:nil]; 70 | 71 | } 72 | } 73 | 74 | - (void)viewWillAppear:(BOOL)animated { 75 | [super viewWillAppear:animated]; 76 | 77 | [self fetchData]; 78 | 79 | [self filterUniqueDate]; 80 | 81 | [self calculateMonthsMoney]; 82 | 83 | [self setTotalLabel]; 84 | 85 | [self.monthTableView reloadData]; 86 | } 87 | 88 | - (void)fetchData { 89 | // 得到所有account 90 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 91 | 92 | NSError *error = nil; 93 | self.dataArray = [NSMutableArray arrayWithArray:[self.managedObjectContext executeFetchRequest:request error:&error]]; 94 | } 95 | 96 | - (void)filterUniqueDate { 97 | NSMutableArray *dateArray = [NSMutableArray array]; 98 | 99 | // 将月份组成一个数组 100 | for (Account *account in self.dataArray) { 101 | // 取前7位的年和月份 102 | [dateArray addObject:[account.date substringToIndex:7]]; 103 | } 104 | 105 | // 用NSSet得到不重复的月份 106 | NSSet *set = [NSSet setWithArray:[dateArray copy]]; 107 | 108 | // 再得到排序后的数组 109 | NSArray *sortDesc = @[[[NSSortDescriptor alloc] initWithKey:nil ascending:YES]]; 110 | self.uniqueDateArray = [NSMutableArray arrayWithArray:[set sortedArrayUsingDescriptors:sortDesc]]; 111 | 112 | } 113 | 114 | - (void)calculateMonthsMoney { 115 | // 先将数据取得添加到暂时数组中,防止每次调用这方法在没有数据改变的情况下金额显示增大 116 | double tmpTotalIncome = 0; 117 | double tmpTotalExpense = 0; 118 | NSMutableArray *tmpMonthIncome = [NSMutableArray array]; 119 | NSMutableArray *tmpMonthExpense = [NSMutableArray array]; 120 | 121 | 122 | for (NSInteger i = 0; i < self.uniqueDateArray.count; i++) { 123 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 124 | 125 | // 过滤月份 126 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@", self.uniqueDateArray[i]]]; 127 | 128 | NSError *error = nil; 129 | NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error]; 130 | 131 | double income = 0; 132 | double expense = 0; 133 | for (Account *account in results) { 134 | if ([account.incomeType isEqualToString:@"income"]) { 135 | income += [account.money doubleValue]; 136 | } else { 137 | expense += [account.money doubleValue]; 138 | } 139 | } 140 | 141 | // 加到暂存总收入支出中 142 | tmpTotalIncome += income; 143 | tmpTotalExpense += expense; 144 | 145 | // 并将结果暂时储存在收入/支出数组相应月份在uniqueDateArray的位置 146 | // 方便到时候设置cell的各个属性 147 | [tmpMonthIncome addObject:[NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:income]]]; 148 | [tmpMonthExpense addObject:[NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:expense]]]; 149 | 150 | } 151 | 152 | // 将暂存值赋给属性以显示在UI上 153 | self.totalIncome = tmpTotalIncome; 154 | self.totalExpense = tmpTotalExpense; 155 | 156 | self.monthIncome = tmpMonthIncome; 157 | self.monthExpense = tmpMonthExpense; 158 | 159 | } 160 | 161 | - (void)setTotalLabel { 162 | // 示意图: 总收入: xxx(不限长度) 总支出: xxx(不限长度) 163 | NSString *incomeString = [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalIncome]]; 164 | NSString *expenseString = [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalExpense]]; 165 | 166 | 167 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"总收入: %@ 总支出: %@", incomeString, expenseString]]; 168 | 169 | 170 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, 4)]; 171 | 172 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(5, incomeString.length)]; 173 | 174 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(5 + incomeString.length + 2, 4)]; 175 | 176 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(5 + incomeString.length + 2 + 5, expenseString.length)]; 177 | 178 | [self.totalDetailLabel setAttributedText:mutString]; 179 | 180 | 181 | // 计算结余 182 | double remainMoney = self.totalIncome - self.totalExpense; 183 | 184 | self.remainMoneyLabel.text = [NSString stringWithFormat:@"结余: %@", [NSNumber numberWithDouble:remainMoney]]; 185 | 186 | } 187 | 188 | #pragma UITableView DataSource 189 | 190 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 191 | return self.uniqueDateArray.count; 192 | } 193 | 194 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 195 | AZXAllHistoryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"monthAccountCell" forIndexPath:indexPath]; 196 | 197 | cell.date.text = self.uniqueDateArray[indexPath.row]; 198 | 199 | NSMutableAttributedString * mutString = [self configMoneyLabelWithIndexPath:indexPath]; 200 | 201 | [cell.money setAttributedText:mutString]; 202 | 203 | return cell; 204 | } 205 | 206 | - (NSMutableAttributedString *)configMoneyLabelWithIndexPath:(NSIndexPath *)indexPath { 207 | // 收入金额 208 | NSString *income = self.monthIncome[indexPath.row]; 209 | 210 | NSString *incomeString = [@"收入: " stringByAppendingString:income]; 211 | 212 | // 为了排版,固定金额数目为7位,不足补空格 213 | for (NSInteger i = income.length; i < 7; i++) { 214 | incomeString = [incomeString stringByAppendingString:@" "]; 215 | } 216 | 217 | // 支出金额(前留一空格) 218 | NSString *expense = self.monthExpense[indexPath.row]; 219 | NSString *expenseString = [@" 支出: " stringByAppendingString:expense]; 220 | 221 | // 排版 222 | for (NSInteger i = expense.length; i < 7; i++) { 223 | expenseString = [expenseString stringByAppendingString:@" "]; 224 | } 225 | 226 | // 合并两个字符串 227 | NSString *moneyString = [incomeString stringByAppendingString:expenseString]; 228 | 229 | // 设置文本不同颜色 230 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:moneyString]; 231 | 232 | // 示意图: 收入: xxxxxxx 支出: xxxxxxx 233 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, 3)]; 234 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(4, 7)]; 235 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(12, 3)]; 236 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(16, 7)]; 237 | 238 | return mutString; 239 | } 240 | 241 | #pragma mark - UITabelView Delegate 242 | 243 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 244 | return YES; 245 | } 246 | 247 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 248 | 249 | if (editingStyle == UITableViewCellEditingStyleDelete) { 250 | // 取得相应日期的数据 251 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 252 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@", self.uniqueDateArray[indexPath.row]]]; 253 | NSError *error = nil; 254 | NSArray *accountToBeDeleted = [self.managedObjectContext executeFetchRequest:request error:&error]; 255 | 256 | // 首先删除CoreData里的数据 257 | for (Account *account in accountToBeDeleted) { 258 | [self.managedObjectContext deleteObject:account]; 259 | } 260 | // 然后移除提供数据源的数组 261 | [self.uniqueDateArray removeObjectAtIndex:indexPath.row]; 262 | // 删除tableView的行 263 | [self.monthTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 264 | // 最后更新UI 265 | [self calculateMonthsMoney]; 266 | 267 | [self setTotalLabel]; 268 | 269 | [self.monthTableView reloadData]; 270 | } 271 | } 272 | 273 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { 274 | // 将detele改为删除 275 | return @" 删除 "; 276 | } 277 | 278 | #pragma mark - Navigation 279 | 280 | // In a storyboard-based application, you will often want to do a little preparation before navigation 281 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 282 | if ([segue.identifier isEqualToString:@"showMonthDetail"]) { 283 | if ([[segue destinationViewController] isKindOfClass:[AZXMonthHIstoryViewController class]]) { 284 | AZXMonthHIstoryViewController *viewController = [segue destinationViewController]; 285 | NSIndexPath *indexPath = [self.monthTableView indexPathForSelectedRow]; 286 | 287 | // 将被点击cell的相应属性传过去 288 | viewController.date = self.uniqueDateArray[indexPath.row]; 289 | } 290 | } 291 | } 292 | 293 | 294 | @end 295 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXMonthHIstoryViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXMonthHIstoryViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXMonthHIstoryViewController : UIViewController 12 | 13 | @property (nonatomic, strong) NSString *date; // 主界面点击cell的date 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXMonthHIstoryViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXMonthHIstoryViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/11. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXMonthHIstoryViewController.h" 10 | #import "AZXAllHistoryTableViewCell.h" 11 | #import "AppDelegate.h" 12 | #import "Account.h" 13 | #import "AZXAccountViewController.h" 14 | #import 15 | 16 | @interface AZXMonthHIstoryViewController () 17 | 18 | @property (weak, nonatomic) IBOutlet UILabel *TotalMoneyLabel; 19 | 20 | @property (weak, nonatomic) IBOutlet UILabel *remainMoneyLabel; 21 | 22 | @property (weak, nonatomic) IBOutlet UITableView *dayTableView; 23 | 24 | @property (strong, nonatomic) NSArray *dataArray; // 储存fetch来的当前月份的Account 25 | 26 | @property (strong, nonatomic) NSMutableArray *dayIncome; // 每天的收入金额 27 | 28 | @property (strong, nonatomic) NSMutableArray *dayExpense; // 每天的支出金额 29 | 30 | 31 | @property (nonatomic, assign) double totalIncome; // 总收入 32 | 33 | @property (nonatomic, assign) double totalExpense; // 总支出 34 | 35 | @property (strong, nonatomic) NSMutableArray *uniqueDateArray; // 储存不重复日期的数组 36 | 37 | @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 38 | 39 | @end 40 | 41 | @implementation AZXMonthHIstoryViewController 42 | 43 | - (void)viewDidLoad { 44 | [super viewDidLoad]; 45 | 46 | self.dayTableView.dataSource = self; 47 | 48 | AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 49 | self.managedObjectContext = appDelegate.managedObjectContext; 50 | 51 | // 数组的初始化 52 | self.dayIncome = [NSMutableArray array]; 53 | self.dayExpense = [NSMutableArray array]; 54 | } 55 | 56 | - (void)viewWillAppear:(BOOL)animated { 57 | [super viewWillAppear:animated]; 58 | 59 | self.navigationItem.title = self.date; 60 | 61 | [self fetchData]; 62 | 63 | [self filterUniqueDate]; 64 | 65 | [self calculateDayMoney]; 66 | 67 | [self setTotalLabel]; 68 | 69 | [self.dayTableView reloadData]; 70 | } 71 | 72 | - (void)fetchData { 73 | // 取得当前月份的account 74 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 75 | 76 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@", self.date]]; 77 | 78 | NSError *error = nil; 79 | self.dataArray = [NSMutableArray arrayWithArray:[self.managedObjectContext executeFetchRequest:request error:&error]]; 80 | 81 | } 82 | 83 | - (void)filterUniqueDate { 84 | NSMutableArray *dateArray = [NSMutableArray array]; 85 | 86 | for (Account *account in self.dataArray) { 87 | [dateArray addObject:account.date]; 88 | } 89 | 90 | NSSet *set = [NSSet setWithArray:[dateArray copy]]; 91 | 92 | NSArray *SortDesc = @[[[NSSortDescriptor alloc] initWithKey:nil ascending:YES]]; 93 | 94 | self.uniqueDateArray = [NSMutableArray arrayWithArray:[set sortedArrayUsingDescriptors:SortDesc]]; 95 | } 96 | 97 | - (void)calculateDayMoney { 98 | // 防止叠加,暂存数组,暂存总额 99 | double tmpTotalIncome = 0; 100 | double tmpTotalExpense = 0; 101 | 102 | NSMutableArray *tmpDayIncome = [NSMutableArray array]; 103 | NSMutableArray *tmpDayExpense = [NSMutableArray array]; 104 | 105 | for (NSInteger i = 0; i < self.uniqueDateArray.count; i++) { 106 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 107 | [request setPredicate:[NSPredicate predicateWithFormat:@"date == %@", self.uniqueDateArray[i]]]; 108 | 109 | NSError *error = nil; 110 | NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error]; 111 | 112 | double income = 0; 113 | double expense = 0; 114 | 115 | for (Account *account in results) { 116 | if ([account.incomeType isEqualToString:@"income"]) { 117 | income += [account.money doubleValue]; 118 | } else { 119 | expense += [account.money doubleValue]; 120 | } 121 | } 122 | 123 | tmpTotalIncome += income; 124 | tmpTotalExpense += expense; 125 | 126 | [tmpDayIncome addObject:[NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:income]]]; 127 | [tmpDayExpense addObject:[NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:expense]]]; 128 | } 129 | 130 | self.totalIncome = tmpTotalIncome; 131 | self.totalExpense = tmpTotalExpense; 132 | 133 | self.dayIncome = tmpDayIncome; 134 | self.dayExpense = tmpDayExpense; 135 | } 136 | 137 | - (void)setTotalLabel { 138 | // 示意图: 总收入: xxx(不限长度) 总支出: xxx(不限长度) 139 | NSString *incomeString = [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalIncome]]; 140 | NSString *expenseString = [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalExpense]]; 141 | 142 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"本月收入: %@ 本月支出: %@", incomeString, expenseString]]; 143 | 144 | 145 | 146 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, 5)]; 147 | 148 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(6, incomeString.length)]; 149 | 150 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(6 + incomeString.length + 2, 5)]; 151 | 152 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(6 + incomeString.length + 2 + 6, expenseString.length)]; 153 | 154 | [self.TotalMoneyLabel setAttributedText:mutString]; 155 | 156 | 157 | // 计算结余 158 | double remainMoney = self.totalIncome - self.totalExpense; 159 | 160 | self.remainMoneyLabel.text = [NSString stringWithFormat:@"结余: %@", [NSNumber numberWithDouble:remainMoney]]; 161 | 162 | } 163 | 164 | 165 | #pragma mark - UITableView DataSource 166 | 167 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 168 | return self.uniqueDateArray.count; 169 | } 170 | 171 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 172 | AZXAllHistoryTableViewCell *cell = [self.dayTableView dequeueReusableCellWithIdentifier:@"dayAccountCell" forIndexPath:indexPath]; 173 | 174 | NSString *fullDate = self.uniqueDateArray[indexPath.row]; 175 | cell.date.text = [fullDate substringFromIndex:5]; 176 | 177 | NSMutableAttributedString * mutString = [self configMoneyLabelWithIndexPath:indexPath]; 178 | 179 | [cell.money setAttributedText:mutString]; 180 | 181 | return cell; 182 | } 183 | 184 | - (NSMutableAttributedString *)configMoneyLabelWithIndexPath:(NSIndexPath *)indexPath { 185 | // 收入金额 186 | NSString *income = self.dayIncome[indexPath.row]; 187 | 188 | NSString *incomeString = [@"收入: " stringByAppendingString:income]; 189 | 190 | // 为了排版,固定金额数目为7位,不足补空格 191 | for (NSInteger i = income.length; i < 7; i++) { 192 | incomeString = [incomeString stringByAppendingString:@" "]; 193 | } 194 | 195 | // 支出金额(前留一空格) 196 | NSString *expense = self.dayExpense[indexPath.row]; 197 | NSString *expenseString = [@" 支出: " stringByAppendingString:expense]; 198 | 199 | // 排版 200 | for (NSInteger i = expense.length; i < 7; i++) { 201 | expenseString = [expenseString stringByAppendingString:@" "]; 202 | } 203 | 204 | // 合并两个字符串 205 | NSString *moneyString = [incomeString stringByAppendingString:expenseString]; 206 | 207 | // 设置文本不同颜色 208 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:moneyString]; 209 | 210 | // 示意图: 收入: xxxxxxx 支出: xxxxxxx 211 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, 3)]; 212 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(4, 7)]; 213 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(12, 3)]; 214 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(16, 7)]; 215 | 216 | return mutString; 217 | } 218 | 219 | #pragma mark - UITabelView Delegate 220 | 221 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 222 | return YES; 223 | } 224 | 225 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 226 | 227 | if (editingStyle == UITableViewCellEditingStyleDelete) { 228 | // 取得相应月份的数据 229 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 230 | [request setPredicate:[NSPredicate predicateWithFormat:@"date == %@", self.uniqueDateArray[indexPath.row]]]; 231 | NSError *error = nil; 232 | NSArray *accountToBeDeleted = [self.managedObjectContext executeFetchRequest:request error:&error]; 233 | 234 | // 首先删除CoreData里的数据 235 | for (Account *account in accountToBeDeleted) { 236 | [self.managedObjectContext deleteObject:account]; 237 | } 238 | // 然后移除提供数据源的数组 239 | [self.uniqueDateArray removeObjectAtIndex:indexPath.row]; 240 | // 删除tableView的行 241 | [self.dayTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 242 | // 最后更新UI 243 | [self calculateDayMoney]; 244 | 245 | [self setTotalLabel]; 246 | 247 | [self.dayTableView reloadData]; 248 | } 249 | } 250 | 251 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { 252 | // 将detele改为删除 253 | return @" 删除 "; 254 | } 255 | 256 | #pragma mark - Navigation 257 | 258 | // In a storyboard-based application, you will often want to do a little preparation before navigation 259 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 260 | if ([segue.identifier isEqualToString:@"showDayDetail"]) { 261 | if ([[segue destinationViewController] isKindOfClass:[AZXAccountViewController class]]) { 262 | AZXAccountViewController *viewController = [segue destinationViewController]; 263 | NSIndexPath *indexPath = [self.dayTableView indexPathForSelectedRow]; 264 | 265 | // 通知AZXAccountViewController是从此页面转过去的,且告诉其日期 266 | viewController.passedDate = self.uniqueDateArray[indexPath.row]; 267 | } 268 | } 269 | } 270 | 271 | 272 | @end 273 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXNewAccountTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXNewAccountTableViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/2/21. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Account.h" 11 | 12 | @class AZXNewAccountTableViewController; 13 | 14 | @protocol PassingDateDelegate ; 15 | @optional 16 | - (void)viewController:(AZXNewAccountTableViewController *)controller didPassDate:(NSString *)date; 17 | // 使用代理将date值传给首页(让其筛选Fetch的managedObject) 18 | @end 19 | 20 | @interface AZXNewAccountTableViewController : UITableViewController 21 | 22 | @property (nonatomic, weak) id delegate; 23 | 24 | @property (nonatomic, assign) BOOL isSegueFromTableView; // 判断是否通过点击cell转来 25 | 26 | @property (nonatomic, strong) Account *accountInSelectedRow; // 点击的cell是第几个 27 | @end 28 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXOperateTypeTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXOperateTypeTableViewCell.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXOperateTypeTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *image; 14 | 15 | @property (weak, nonatomic) IBOutlet UILabel *type; 16 | 17 | @property (weak, nonatomic) IBOutlet UILabel *operation; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXOperateTypeTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXOperateTypeTableViewCell.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXOperateTypeTableViewCell.h" 10 | 11 | @implementation AZXOperateTypeTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXOperateTypeTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXOperateTypeTableViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXOperateTypeTableViewController : UITableViewController 12 | 13 | @property (nonatomic, strong) NSString *operationType; // 判断进行哪一种操作 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXOperateTypeTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXOperateTypeTableViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | /* 9 | object Key 10 | 收入类型组 incomeAZX 11 | 支出类型组 expenseAZX 12 | 13 | */ 14 | 15 | #import "AZXOperateTypeTableViewController.h" 16 | #import "AZXOperateTypeTableViewCell.h" 17 | #import "AppDelegate.h" 18 | #import "Account.h" 19 | #import 20 | 21 | @interface AZXOperateTypeTableViewController () 22 | 23 | @property (nonatomic, strong) NSMutableArray *typeArray; 24 | 25 | @property (nonatomic, strong) NSString *incomeType; 26 | 27 | @property (nonatomic, strong) NSUserDefaults *defaults; 28 | 29 | @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 30 | 31 | @end 32 | 33 | @implementation AZXOperateTypeTableViewController 34 | 35 | - (NSString *)incomeType { 36 | if (!_incomeType) { 37 | _incomeType = @"expense"; // 默认为支出 38 | } 39 | return _incomeType; 40 | } 41 | 42 | - (void)viewDidLoad { 43 | [super viewDidLoad]; 44 | 45 | self.defaults = [NSUserDefaults standardUserDefaults]; 46 | 47 | AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 48 | self.managedObjectContext = appDelegate.managedObjectContext; 49 | 50 | if ([self.operationType isEqualToString:@"deleteAndMoveType"]) { 51 | // 如果是删除和移动类别操作,并且第一次进入此界面,弹出教程 52 | [self judgeFirstLoadThisView]; 53 | 54 | // 进入编辑模式 55 | [self.tableView setEditing:YES animated:YES]; 56 | } 57 | } 58 | 59 | - (void)judgeFirstLoadThisView { 60 | if (![self.defaults boolForKey:@"haveLoadedAZXOperateTypeTableViewControllerAddAndDelete"]) { 61 | // 第一次进入此页面 62 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"教程" message:@"点击类别左边的红色减号删除,按住并拖动右边的三杠符号进行位置排序" preferredStyle:UIAlertControllerStyleAlert]; 63 | 64 | UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"知道了,不再提醒" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 65 | [self.defaults setBool:YES forKey:@"haveLoadedAZXOperateTypeTableViewControllerAddAndDelete"]; 66 | }]; 67 | 68 | [alert addAction:actionOK]; 69 | 70 | [self presentViewController:alert animated:YES completion:nil]; 71 | } 72 | } 73 | 74 | 75 | - (void)viewWillDisappear:(BOOL)animated { 76 | [super viewWillDisappear:animated]; 77 | // 将要退出界面时,将数组数据保存 78 | [self.defaults setObject:self.typeArray forKey:[self.incomeType stringByAppendingString:@"AZX"]]; 79 | } 80 | 81 | - (IBAction)segControlChanged:(UISegmentedControl *)sender { 82 | if (sender.selectedSegmentIndex == 0) { 83 | self.incomeType = @"expense"; 84 | 85 | [self refreshAll]; 86 | [self.tableView reloadData]; 87 | } else { 88 | self.incomeType = @"income"; 89 | 90 | [self refreshAll]; 91 | [self.tableView reloadData]; 92 | } 93 | } 94 | 95 | - (void)viewWillAppear:(BOOL)animated { 96 | [super viewWillAppear:animated]; 97 | 98 | [self refreshAll]; 99 | 100 | } 101 | 102 | - (void)refreshAll { 103 | // 取得储存的支出/收入类型数组 104 | if ([self.incomeType isEqualToString:@"income"]) { 105 | // objectForKey总是返回不可变的对象(即使存进去的时候是可变的) 106 | self.typeArray = [NSMutableArray arrayWithArray:[self.defaults objectForKey:@"incomeAZX"]]; 107 | } else { 108 | self.typeArray = [NSMutableArray arrayWithArray:[self.defaults objectForKey:@"expenseAZX"]]; 109 | } 110 | 111 | } 112 | 113 | #pragma mark - Table view data source 114 | 115 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 116 | return self.typeArray.count; 117 | } 118 | 119 | 120 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 121 | AZXOperateTypeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"operateTypeCell" forIndexPath:indexPath]; 122 | 123 | cell.type.text = self.typeArray[indexPath.row]; 124 | 125 | // 得到类别名相应的图片 126 | cell.image.image = [UIImage imageNamed:[self.defaults objectForKey:cell.type.text]]; 127 | 128 | if ([self.operationType isEqualToString:@"changeType"]) { 129 | // 进行重命名操作 130 | cell.operation.text = @"重命名"; 131 | cell.operation.userInteractionEnabled = YES; 132 | 133 | UITapGestureRecognizer *tapLabel = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapRename:)]; 134 | 135 | [cell.operation addGestureRecognizer:tapLabel]; 136 | } else if ([self.operationType isEqualToString:@"deleteAndMoveType"]) { 137 | // 进行排序和删除操作 138 | cell.operation.text = @""; 139 | } 140 | 141 | return cell; 142 | } 143 | 144 | #pragma mark - Add or delete methods 145 | 146 | - (void)addType { 147 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"添加类别" message:@"输入新类别名称" preferredStyle:UIAlertControllerStyleAlert]; 148 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 149 | textField.placeholder = @"点击输入"; 150 | }]; 151 | UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 152 | // 新加入类型保存起来并刷新tableView 153 | [self.typeArray addObject:alert.textFields[0].text]; 154 | [self.tableView reloadData]; 155 | // 保存数据 156 | [self.defaults setObject:self.typeArray forKey:[self.incomeType stringByAppendingString:@"AZX"]]; 157 | }]; 158 | 159 | UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 160 | 161 | [alert addAction:actionCancel]; 162 | [alert addAction:actionOK]; 163 | 164 | [self presentViewController:alert animated:YES completion:nil]; 165 | } 166 | 167 | 168 | #pragma mark - Rename methods 169 | 170 | - (void)tapRename:(UITapGestureRecognizer *)gesture { 171 | // 通过点击位置确定点击的cell位置 172 | NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[gesture locationInView:self.tableView]]; 173 | 174 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"修改名称" message:@"请输入新类别名称" preferredStyle:UIAlertControllerStyleAlert]; 175 | 176 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 177 | textField.placeholder = self.typeArray[indexPath.row]; 178 | }]; 179 | 180 | UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 181 | // 保存在Assets中的图片的名称 182 | NSString *imageName = [self.defaults objectForKey:self.typeArray[indexPath.row]]; 183 | 184 | // 将旧的类别名与图片名称的关联除去 185 | [self.defaults removeObjectForKey:self.typeArray[indexPath.row]]; 186 | 187 | // 将新的类别名与图片名称相关联 188 | [self.defaults setObject:imageName forKey:alert.textFields[0].text]; 189 | 190 | // 修改数组中存放的类别名称 191 | self.typeArray[indexPath.row] = alert.textFields[0].text; 192 | 193 | // 刷新tableView 194 | [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 195 | 196 | // 保存数据 197 | [self.defaults setObject:self.typeArray forKey:[self.incomeType stringByAppendingString:@"AZX"]]; 198 | }]; 199 | 200 | UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 201 | 202 | [alert addAction:actionCancel]; 203 | [alert addAction:actionOK]; 204 | 205 | [self presentViewController:alert animated:YES completion:nil]; 206 | 207 | } 208 | 209 | 210 | #pragma mark - Move tableView delegate methods 211 | 212 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 213 | if ([self.operationType isEqualToString:@"deleteAndMoveType"]) { 214 | return YES; 215 | } else { 216 | return NO; 217 | } 218 | } 219 | 220 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 221 | // 需要移动的行 222 | NSString *typeToMove = self.typeArray[fromIndexPath.row]; 223 | 224 | [self.typeArray removeObjectAtIndex:fromIndexPath.row]; 225 | [self.typeArray insertObject:typeToMove atIndex:toIndexPath.row]; 226 | 227 | // 保存数据 228 | [self.defaults setObject:self.typeArray forKey:[self.incomeType stringByAppendingString:@"AZX"]]; 229 | } 230 | 231 | 232 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 233 | if (editingStyle == UITableViewCellEditingStyleDelete) { 234 | // 将要删除的类别名与图片名称的关联除去 235 | [self.defaults removeObjectForKey:self.typeArray[indexPath.row]]; 236 | 237 | // 将所有此类别的账单一并移去 238 | [self removeAllAccountOfOneType:self.typeArray[indexPath.row]]; 239 | 240 | // 将其从tableView中移除 241 | [self.typeArray removeObjectAtIndex:indexPath.row]; 242 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 243 | 244 | // 保存数据 245 | [self.defaults setObject:self.typeArray forKey:[self.incomeType stringByAppendingString:@"AZX"]]; 246 | } 247 | } 248 | 249 | - (void)removeAllAccountOfOneType:(NSString *)type { 250 | // 删除所有此类别的account 251 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 252 | [request setPredicate:[NSPredicate predicateWithFormat:@"type == %@", type]]; 253 | 254 | NSError *error = nil; 255 | NSArray *accounts = [self.managedObjectContext executeFetchRequest:request error:&error]; 256 | 257 | for (Account *account in accounts) { 258 | [self.managedObjectContext deleteObject:account]; 259 | } 260 | } 261 | 262 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { 263 | // 将detele改为删除 264 | return @" 删除 "; 265 | } 266 | 267 | /* 268 | #pragma mark - Navigation 269 | 270 | // In a storyboard-based application, you will often want to do a little preparation before navigation 271 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 272 | // Get the new view controller using [segue destinationViewController]. 273 | // Pass the selected object to the new view controller. 274 | } 275 | */ 276 | 277 | @end 278 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieTableViewCell.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/13. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXPieTableViewCell : UITableViewCell 12 | @property (weak, nonatomic) IBOutlet UIView *colorView; 13 | 14 | @property (weak, nonatomic) IBOutlet UILabel *moneyLabel; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieTableViewCell.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/13. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXPieTableViewCell.h" 10 | 11 | @implementation AZXPieTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieView.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/12. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class AZXPieView; 12 | 13 | @protocol AZXPieViewDataSource 14 | 15 | @required 16 | 17 | - (NSArray *)percentsForPieView:(AZXPieView *)pieView; 18 | - (NSArray *)typesForPieView:(AZXPieView *)pieView; 19 | - (NSArray *)colorsForPieView:(AZXPieView *)pieView; 20 | 21 | @end 22 | 23 | @interface AZXPieView : UIView 24 | 25 | @property (weak, nonatomic) id dataSource; 26 | 27 | - (void)reloadData; 28 | 29 | - (void)removeAllLabel; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieView.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/12. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXPieView.h" 10 | 11 | @interface AZXPieView () 12 | 13 | @property (strong, nonatomic) NSArray *colorArray; 14 | 15 | @property (strong, nonatomic) NSArray *typeArray; 16 | 17 | @property (strong, nonatomic) NSArray *percentArray; 18 | 19 | @property (strong, nonatomic) NSMutableArray *labelArray; 20 | 21 | @end 22 | 23 | //IB_DESIGNABLE 24 | @implementation AZXPieView 25 | 26 | - (void)drawRect:(CGRect)rect { 27 | // 先将背景色设为默认 28 | [[UIColor whiteColor] set]; 29 | UIRectFill(rect); 30 | 31 | self.labelArray = [NSMutableArray array]; 32 | 33 | if (self.dataSource && [self.dataSource respondsToSelector:@selector(percentsForPieView:)] && [self.dataSource respondsToSelector:@selector(typesForPieView:)] && [self.dataSource respondsToSelector:@selector(colorsForPieView:)]) { 34 | // 如果代理存在且实现了这些方法 35 | self.typeArray = [self.dataSource typesForPieView:self]; 36 | self.percentArray = [self.dataSource percentsForPieView:self]; 37 | self.colorArray = [self.dataSource colorsForPieView:self]; 38 | 39 | // 计算得出各自的起始角度 40 | NSMutableArray *startAngleArray = [NSMutableArray array]; 41 | 42 | CGFloat angle = 0; 43 | 44 | for (NSInteger i = 0; i < self.percentArray.count; i++) { 45 | [startAngleArray addObject:[NSNumber numberWithDouble:angle]]; 46 | angle += [self.percentArray[i] doubleValue] * 2 * M_PI / 100; 47 | } 48 | 49 | for (NSInteger j = 0; j < self.typeArray.count; j++) { 50 | [self drawSectorWithStartAngle:[startAngleArray[j] doubleValue] Percent:[self.percentArray[j] doubleValue]/100 Type:self.typeArray[j] Color:self.colorArray[j]]; 51 | } 52 | 53 | } 54 | 55 | } 56 | 57 | - (void)drawSectorWithStartAngle:(double)startAngle Percent:(double)percent Type:(NSString *)type Color:(UIColor *)color { 58 | CGFloat radius = self.frame.size.width > self.frame.size.height? self.frame.size.height/2 : self.frame.size.width/2; // 半径取矩形短的一边 59 | // self.center显示是在超类中的位置,要将偏移量减去 60 | CGPoint center = self.center; 61 | center.x -= self.frame.origin.x; 62 | center.y -= self.frame.origin.y; 63 | 64 | UIBezierPath *path = [UIBezierPath bezierPath]; 65 | [path moveToPoint:center]; 66 | 67 | [path addArcWithCenter:center radius:radius startAngle:startAngle endAngle:startAngle + 2*M_PI*percent clockwise:YES]; 68 | 69 | [path addLineToPoint:center]; 70 | 71 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; 72 | 73 | label.text = type; 74 | 75 | label.textColor = [UIColor blackColor]; 76 | 77 | label.backgroundColor = [UIColor clearColor]; 78 | 79 | label.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; 80 | 81 | label.textAlignment = NSTextAlignmentCenter; 82 | 83 | [label sizeToFit]; 84 | 85 | // 判断扇形能不能容纳下label的内容 86 | // 判断label在垂直于过扇形中点的半径方向的投影是否大于扇形在该处的长度,">"后面用的余弦定理(角度小于180度时有效,故前加一个percent < 0.5的判定) 87 | // 或者只要小于3%的通通设为.. 88 | if ((percent < 0.5 && label.frame.size.width * fabs(sin(startAngle + M_PI*percent)) > sqrt(2*(radius/2)*(radius/2) - 2*radius/2*radius/2*cos(2*M_PI*percent))) || percent < 0.03) { 89 | label.text = @".."; 90 | } 91 | 92 | // 找到扇形中心点 93 | CGFloat centerX = center.x + (radius/2*cos(startAngle + M_PI*percent)); 94 | CGFloat centerY = center.y + (radius/2*sin(startAngle + M_PI*percent)); 95 | 96 | label.center = CGPointMake(centerX, centerY); 97 | 98 | 99 | [self addSubview:label]; 100 | 101 | [self.labelArray addObject:label]; // 将label放入数组,离开界面时一并移除 102 | 103 | [color set]; 104 | 105 | [path fill]; 106 | 107 | } 108 | 109 | - (void)reloadData { 110 | [self setNeedsDisplay]; 111 | } 112 | 113 | - (void)removeAllLabel { 114 | for (UILabel *label in self.labelArray) { 115 | [label removeFromSuperview]; 116 | } 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/12. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXPieViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXPieViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXPieViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/12. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXPieViewController.h" 10 | #import "AZXPieView.h" 11 | #import "AppDelegate.h" 12 | #import "Account.h" 13 | #import "AZXPieTableViewCell.h" 14 | #import "AZXTypeDetailViewController.h" 15 | #import 16 | 17 | @interface AZXPieViewController () 18 | 19 | @property (weak, nonatomic) IBOutlet AZXPieView *pieView; 20 | 21 | @property (weak, nonatomic) IBOutlet UITableView *typeTableView; 22 | 23 | @property (weak, nonatomic) IBOutlet UILabel *moneyLabel; 24 | 25 | @property (strong, nonatomic) IBOutlet UISwipeGestureRecognizer *rightSwipe; // 右滑手势 26 | 27 | @property (strong, nonatomic) IBOutlet UISwipeGestureRecognizer *leftSwipe; // 左滑手势 28 | 29 | @property (strong, nonatomic) UILabel *nullLabel; // 用来显示"暂无数据" 30 | 31 | @property (strong, nonatomic) NSString *incomeType; 32 | 33 | @property (assign, nonatomic) double totalMoney; // 收入/支出总额 34 | 35 | @property (strong, nonatomic) NSArray *dataArray; // fetch来的Accounts 36 | 37 | @property (strong, nonatomic) NSArray *uniqueDateArray; 38 | 39 | @property (strong, nonatomic) NSArray *uniqueTypeArray; 40 | 41 | @property (strong, nonatomic) NSArray *sortedMoneyArray; 42 | 43 | @property (strong, nonatomic) NSArray *sortedPercentArray; // 相应类别所占总金额的比例 44 | 45 | @property (strong, nonatomic) NSDictionary *dict; // 储存有[type:money]的字典 46 | 47 | @property (assign, nonatomic) NSInteger currentIndex; // 当前要显示的数据的index(随swipe而增减) 48 | 49 | @property (strong, nonatomic) NSString *currentDateString; // 当前日期,用来显示与筛选fetch结果 50 | 51 | @property (strong, nonatomic) NSDate *currentDate; // 用来swipe时加减日期 52 | 53 | @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 54 | 55 | @property (strong, nonatomic) NSArray *colors; // 一条渐变的颜色带 56 | 57 | @property (strong, nonatomic) NSArray *colorArray; // 储存各种颜色(对应不同的type) 58 | 59 | @end 60 | 61 | @implementation AZXPieViewController 62 | 63 | - (NSInteger)currentIndex { 64 | if (!_currentIndex) { 65 | _currentIndex = 0; // 默认为0 66 | } 67 | return _currentIndex; 68 | } 69 | 70 | - (NSString *)incomeType { 71 | if (!_incomeType) { 72 | _incomeType = @"expense"; // 默认为支出 73 | } 74 | return _incomeType; 75 | } 76 | 77 | - (NSArray *)colors { 78 | if (!_colors) { 79 | _colors = @[[UIColor colorWithRed:252/255.0 green:25/255.0 blue:28/255.0 alpha:1], 80 | [UIColor colorWithRed:254/255.0 green:200/255.0 blue:46/255.0 alpha:1], 81 | [UIColor colorWithRed:217/255.0 green:253/255.0 blue:53/255.0 alpha:1], 82 | [UIColor colorWithRed:42/255.0 green:253/255.0 blue:130/255.0 alpha:1], 83 | [UIColor colorWithRed:43/255.0 green:244/255.0 blue:253/255.0 alpha:1], 84 | [UIColor colorWithRed:18/255.0 green:92/255.0 blue:249/255.0 alpha:1], 85 | [UIColor colorWithRed:219/255.0 green:39/255.0 blue:249/255.0 alpha:1], 86 | [UIColor colorWithRed:253/255.0 green:105/255.0 blue:33/255.0 alpha:1], 87 | [UIColor colorWithRed:255/255.0 green:245/255.0 blue:54/255.0 alpha:1], 88 | [UIColor colorWithRed:140/255.0 green:253/255.0 blue:49/255.0 alpha:1], 89 | [UIColor colorWithRed:44/255.0 green:253/255.0 blue:218/255.0 alpha:1], 90 | [UIColor colorWithRed:29/255.0 green:166/255.0 blue:250/255.0 alpha:1], 91 | [UIColor colorWithRed:142/255.0 green:37/255.0 blue:248/255.0 alpha:1], 92 | [UIColor colorWithRed:249/255.0 green:31/255.0 blue:181/255.0 alpha:1]]; 93 | 94 | } // 共14种颜色,从红到紫,呈彩虹状渐变 95 | return _colors; 96 | } 97 | 98 | - (IBAction)segValueChanged:(UISegmentedControl *)sender { 99 | if (sender.selectedSegmentIndex == 0) { 100 | self.incomeType = @"expense"; 101 | [self refreshAll]; 102 | } else { 103 | self.incomeType = @"income"; 104 | [self refreshAll]; 105 | } 106 | } 107 | 108 | - (void)viewDidLoad { 109 | [super viewDidLoad]; 110 | 111 | self.typeTableView.dataSource = self; 112 | self.pieView.dataSource = self; 113 | 114 | AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 115 | self.managedObjectContext = appDelegate.managedObjectContext; 116 | 117 | [self setSwipeGesture]; 118 | 119 | [self judgeFirstLoadThisView]; 120 | } 121 | 122 | - (void)judgeFirstLoadThisView { 123 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 124 | 125 | if (![defaults boolForKey:@"haveLoadedAZXPieViewController"]) { 126 | // 第一次进入此页面 127 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"教程" message:@"首页显示本月的收支统计图,手指左右划动屏幕可改变当前显示月份,要查看某一类别的详细情况,点击该行" preferredStyle:UIAlertControllerStyleAlert]; 128 | 129 | UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"知道了,不再提醒" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 130 | [defaults setBool:YES forKey:@"haveLoadedAZXPieViewController"]; 131 | }]; 132 | 133 | [alert addAction:actionOK]; 134 | 135 | [self presentViewController:alert animated:YES completion:nil]; 136 | 137 | } 138 | } 139 | 140 | 141 | - (void)viewWillAppear:(BOOL)animated { 142 | [super viewWillAppear:animated]; 143 | 144 | [self refreshAll]; 145 | } 146 | 147 | - (void)viewWillDisappear:(BOOL)animated { 148 | // 离开界面时将图上label全部移除 149 | [self.pieView removeAllLabel]; 150 | } 151 | 152 | 153 | 154 | - (void)refreshAll { 155 | [self.pieView removeAllLabel]; 156 | 157 | [self.nullLabel removeFromSuperview]; 158 | 159 | [self fetchData]; 160 | 161 | [self filterData]; 162 | 163 | [self setMoneyLabel]; 164 | 165 | [self.typeTableView reloadData]; 166 | 167 | [self.pieView reloadData]; 168 | } 169 | 170 | - (void)setSwipeGesture { 171 | // 分别设置左右滑动手势 172 | self.leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)]; 173 | self.rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)]; 174 | 175 | [self.view addGestureRecognizer:self.leftSwipe]; 176 | [self.view addGestureRecognizer:self.rightSwipe]; 177 | 178 | self.leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft; 179 | self.rightSwipe.direction = UISwipeGestureRecognizerDirectionRight; 180 | } 181 | 182 | - (void)handleSwipe:(UISwipeGestureRecognizer *)gesture { 183 | // 创建一个标准日历 184 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 185 | 186 | NSDateComponents *comps = [[NSDateComponents alloc] init]; 187 | 188 | if (gesture.direction == UISwipeGestureRecognizerDirectionLeft) { 189 | // 左滑月份加1 190 | [comps setMonth:1]; 191 | self.currentDate = [calendar dateByAddingComponents:comps toDate:self.currentDate options:0]; 192 | } else if (gesture.direction == UISwipeGestureRecognizerDirectionRight) { 193 | // 右滑月份减1 194 | [comps setMonth:-1]; 195 | self.currentDate = [calendar dateByAddingComponents:comps toDate:self.currentDate options:0]; 196 | } 197 | 198 | [self refreshAll]; 199 | } 200 | 201 | - (void)fetchData { 202 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 203 | 204 | // 设置日期格式 205 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 206 | dateFormatter.dateFormat = @"yyyy-MM-dd"; 207 | 208 | if (self.currentDateString == nil) { 209 | // 如果还未设置,默认显示当前所处月份 210 | self.currentDate = [NSDate date]; 211 | self.currentDateString = [[dateFormatter stringFromDate:self.currentDate] substringToIndex:7]; 212 | 213 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@ and incomeType == %@", self.currentDateString, self.incomeType]]; 214 | } else { 215 | self.currentDateString = [[dateFormatter stringFromDate:self.currentDate] substringToIndex:7]; 216 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@ and incomeType == %@", self.currentDateString, self.incomeType]]; 217 | } 218 | 219 | NSError *error = nil; 220 | self.dataArray = [self.managedObjectContext executeFetchRequest:request error:&error]; 221 | 222 | if (self.dataArray.count == 0) { 223 | // 如果没有数据,中间显示"暂无数据" 224 | self.nullLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; 225 | self.nullLabel.text = @"暂无数据"; 226 | self.nullLabel.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; 227 | self.nullLabel.textColor = [UIColor lightGrayColor]; 228 | [self.nullLabel sizeToFit]; 229 | self.nullLabel.center = self.view.center; 230 | [self.view addSubview:self.nullLabel]; 231 | } 232 | } 233 | 234 | 235 | // 得到了totalMoney(总金额),sortedMoneyArray(某一类别的金额的数组),uniqueTypeArray(类别数组,与左边的数组排序相同),uniqueDateArray(日期数组),sortedPercentArray(每个类别所花金额占总金额的比例),colorArray(储存各种颜色对应不同的type) 236 | - (void)filterData { 237 | // 设置各个属性的暂存数组,防止直接数据加入属性多次调用方法导致数据叠加 238 | NSMutableArray *tmpTypeArray = [NSMutableArray array]; 239 | NSMutableArray *tmpAccountArray = [NSMutableArray array]; 240 | NSDictionary *tmpDict = [NSMutableDictionary dictionary]; 241 | NSMutableArray *tmpMoneyArray = [NSMutableArray array]; 242 | NSMutableArray *tmpDateArray = [NSMutableArray array]; 243 | NSMutableArray *tmpSortedPercentArray = [NSMutableArray array]; 244 | NSMutableArray *tmpColorArray = [NSMutableArray array]; 245 | 246 | double tmpMoney = 0; 247 | for (Account *account in self.dataArray) { 248 | [tmpTypeArray addObject:account.type]; 249 | [tmpAccountArray addObject:account]; 250 | tmpMoney += [account.money doubleValue]; 251 | [tmpDateArray addObject:[account.date substringToIndex:7]]; 252 | } 253 | 254 | self.totalMoney = tmpMoney; 255 | 256 | // 去掉重复元素 257 | NSSet *typeSet = [NSSet setWithArray:[tmpTypeArray copy]]; 258 | 259 | // 260 | tmpTypeArray = [NSMutableArray array]; 261 | 262 | // 得到降序的无重复元素的日期数组 263 | NSSet *dateSet = [NSSet setWithArray:[tmpDateArray copy]]; 264 | self.uniqueDateArray = [dateSet sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:nil ascending:NO]]]; 265 | 266 | for (NSString *type in typeSet) { 267 | // 从中过滤其中一个类别的所有Account,然后得到一个类别的总金额 268 | NSArray *array = [tmpAccountArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"type == %@", type]]; 269 | 270 | double totalMoneyInOneType = 0; 271 | for (Account *account in array) { 272 | totalMoneyInOneType += [account.money doubleValue]; 273 | } 274 | 275 | // 将金额封装成NSNumber来排序 276 | [tmpMoneyArray addObject:[NSNumber numberWithDouble:totalMoneyInOneType]]; 277 | 278 | // 将type加入数组 279 | [tmpTypeArray addObject:type]; 280 | 281 | } 282 | 283 | // 这里使用字典是为了使type和money能关联起来,而且因为money要排序的原因无法使它们在各自数组保持相同的index,所以用字典的方法 284 | tmpDict = [NSDictionary dictionaryWithObjects:[tmpMoneyArray copy] forKeys:[tmpTypeArray copy]]; 285 | 286 | // 降序排列 287 | self.sortedMoneyArray = [tmpMoneyArray sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:nil ascending:NO]]]; 288 | 289 | NSMutableArray *tmpTypes = [NSMutableArray array]; 290 | NSInteger x = 0; 291 | 292 | double tmpTotalPercent = 0; 293 | 294 | for (NSInteger i = 0; i < self.sortedMoneyArray.count; i++) { 295 | // 将相应百分比(小数点后两位)加入数组 296 | // 此处为了总和为100%,将最后一个设为总额减去数组前除最后一个外所有的元素的百分比 297 | double money = [self.sortedMoneyArray[i] doubleValue]; 298 | 299 | double percent = [[NSString stringWithFormat:@"%.2f",money/self.totalMoney*100] doubleValue]; 300 | 301 | if (i != self.sortedMoneyArray.count - 1) { 302 | // 如果不是数组最后一个的话,直接加入数组 303 | [tmpSortedPercentArray addObject:[NSNumber numberWithDouble:percent]]; 304 | // 并累计前面百分比的总和 305 | tmpTotalPercent += percent; 306 | } else { 307 | // 如果是最后一个元素,通过用1减去前面的总和得到 308 | [tmpSortedPercentArray addObject:[NSNumber numberWithDouble:[[NSString stringWithFormat:@"%.2f", 100-tmpTotalPercent] doubleValue]]]; 309 | } 310 | 311 | // 将相应颜色加入数组(超过数组的14时从头开始) 312 | [tmpColorArray addObject:self.colors[i%14]]; 313 | 314 | // 将相应类型加入数组 315 | // 因为可能一个金额对应着多个类型,判断是否出现此情况,若出现,则将x++, 取出数组其余类型 316 | if (i > 0 && (self.sortedMoneyArray[i-1] == self.sortedMoneyArray[i])) { 317 | x++; 318 | } else { 319 | x = 0; 320 | } 321 | NSString *type = [tmpDict allKeysForObject:self.sortedMoneyArray[i]][x]; 322 | // 此数组中加入的顺序与moneyArray中一样 323 | [tmpTypes addObject:type]; 324 | } 325 | 326 | self.sortedPercentArray = [tmpSortedPercentArray copy]; 327 | self.colorArray = [tmpColorArray copy]; 328 | self.uniqueTypeArray = [tmpTypes copy]; 329 | } 330 | 331 | - (void)setMoneyLabel { 332 | NSMutableAttributedString *mutString; 333 | if ([self.incomeType isEqualToString:@"income"]) { 334 | mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ 总收入: %@", self.currentDateString, [NSNumber numberWithDouble:self.totalMoney]]]; 335 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(13, [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalMoney]].length)]; 336 | } else { 337 | mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ 总支出: %@", self.currentDateString, [NSNumber numberWithDouble:self.totalMoney]]]; 338 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(13, [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalMoney]].length)]; 339 | 340 | } 341 | 342 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, 12)]; 343 | 344 | [self.moneyLabel setAttributedText:mutString]; 345 | } 346 | 347 | #pragma mark - UITableView DataSource 348 | 349 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 350 | return self.uniqueTypeArray.count; 351 | } 352 | 353 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 354 | AZXPieTableViewCell *cell = [self.typeTableView dequeueReusableCellWithIdentifier:@"pieTypeCell" forIndexPath:indexPath]; 355 | 356 | cell.colorView.backgroundColor = self.colorArray[indexPath.row]; 357 | 358 | NSString *type = self.uniqueTypeArray[indexPath.row]; 359 | NSNumber *money = self.sortedMoneyArray[indexPath.row]; 360 | 361 | NSNumber *percent = self.sortedPercentArray[indexPath.row]; 362 | NSString *percentString = [NSString stringWithFormat:@"%@", percent]; 363 | 364 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ %@ %@%%", type, money, [self filterLastZeros:percentString]]]; 365 | 366 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, type.length)]; 367 | 368 | // 计算金额显示的长度 369 | NSInteger moneyLength = [NSString stringWithFormat:@"%@", money].length; 370 | 371 | if ([self.incomeType isEqualToString:@"income"]) { 372 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(type.length + 5, moneyLength)]; 373 | } else { 374 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(type.length + 5, moneyLength)]; 375 | } 376 | 377 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(type.length + 5 + moneyLength + 5, percentString.length + 1)]; 378 | 379 | [cell.moneyLabel setAttributedText:mutString]; 380 | 381 | return cell; 382 | } 383 | 384 | - (NSString *)filterLastZeros:(NSString *)string { 385 | NSString *str = string; 386 | if ([str containsString:@"."] && [string substringFromIndex:[string rangeOfString:@"."].location].length > 3) { 387 | // 如果小数点后大于2位,只保留两位 388 | str = [string substringToIndex:[string rangeOfString:@"."].location+3]; 389 | } 390 | if ([str containsString:@"."]) { 391 | if ([[str substringFromIndex:str.length-1] isEqualToString: @"0"]) { 392 | // 如果最后一位为0,舍弃 393 | return [str substringToIndex:str.length-1]; 394 | } else if ([[str substringFromIndex:str.length-2] isEqualToString:@"00"]) { 395 | // 如果后两位为0,舍弃 396 | return [str substringToIndex:str.length-2]; 397 | } else { 398 | return str; 399 | } 400 | } 401 | return str; 402 | } 403 | 404 | 405 | #pragma mark - AZXPieView DataSource 406 | 407 | - (NSArray *)percentsForPieView:(AZXPieView *)pieView { 408 | return self.sortedPercentArray; 409 | } 410 | 411 | - (NSArray *)colorsForPieView:(AZXPieView *)pieView { 412 | return self.colorArray; 413 | } 414 | 415 | - (NSArray *)typesForPieView:(AZXPieView *)pieView { 416 | return self.uniqueTypeArray; 417 | } 418 | 419 | 420 | #pragma mark - Navigation 421 | 422 | // In a storyboard-based application, you will often want to do a little preparation before navigation 423 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 424 | if ([segue.identifier isEqualToString:@"showTypeDetail"]) { 425 | if ([[segue destinationViewController] isKindOfClass:[AZXTypeDetailViewController class]]) { 426 | AZXTypeDetailViewController *viewController = [segue destinationViewController]; 427 | viewController.date = self.currentDateString; 428 | 429 | viewController.incomeType = self.incomeType; 430 | 431 | NSIndexPath *indexPath = [self.typeTableView indexPathForSelectedRow]; 432 | 433 | viewController.type = self.uniqueTypeArray[indexPath.row]; 434 | 435 | } 436 | } 437 | } 438 | 439 | 440 | @end 441 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXSettingTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXSettingTableViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXSettingTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXTallyBook.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | AZXTallyBook.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXTallyBook.xcdatamodeld/AZXTallyBook.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXTypeDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AZXTypeDetailViewController.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXTypeDetailViewController : UIViewController 12 | 13 | // 接收要显示哪一个月的哪一种类型的支出/收入 14 | @property (nonatomic, strong) NSString *date; 15 | 16 | @property (nonatomic, strong) NSString *type; 17 | 18 | @property (nonatomic, strong) NSString *incomeType; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /AZXTallyBook/AZXTypeDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXTypeDetailViewController.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/14. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AZXTypeDetailViewController.h" 10 | #import "AppDelegate.h" 11 | #import "Account.h" 12 | #import "AZXAllHistoryTableViewCell.h" 13 | #import "AZXAccountViewController.h" 14 | #import 15 | 16 | @interface AZXTypeDetailViewController () 17 | 18 | @property (weak, nonatomic) IBOutlet UILabel *moneyLabel; 19 | 20 | @property (weak, nonatomic) IBOutlet UITableView *typeTableView; 21 | 22 | @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 23 | 24 | @property (strong, nonatomic) NSArray *dataArray; // fetch而来的数据 25 | 26 | @property (strong, nonatomic) NSArray *uniqueDateArray; 27 | 28 | @property (strong, nonatomic) NSArray *uniqueMoneyArray; 29 | 30 | @property (assign, nonatomic) double totalMoney; 31 | 32 | @end 33 | 34 | @implementation AZXTypeDetailViewController 35 | 36 | - (void)viewDidLoad { 37 | [super viewDidLoad]; 38 | 39 | self.typeTableView.dataSource = self; 40 | 41 | AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 42 | self.managedObjectContext = appDelegate.managedObjectContext; 43 | } 44 | 45 | - (void)viewWillAppear:(BOOL)animated { 46 | [super viewWillAppear:animated]; 47 | 48 | [self fetchData]; 49 | 50 | [self filterData]; 51 | 52 | [self setLabel]; 53 | 54 | [self.typeTableView reloadData]; 55 | } 56 | 57 | - (void)fetchData { 58 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"]; 59 | 60 | [request setPredicate:[NSPredicate predicateWithFormat:@"date beginswith[c] %@ and type == %@ and incomeType == %@", self.date, self.type, self.incomeType]]; 61 | 62 | NSError *error = nil; 63 | self.dataArray = [self.managedObjectContext executeFetchRequest:request error:&error]; 64 | } 65 | 66 | - (void)filterData { 67 | NSMutableArray *tmpDateArray = [NSMutableArray array]; 68 | NSMutableArray *tmpMoneyArray = [NSMutableArray array]; 69 | double tmpTotalMoney = 0; 70 | 71 | for (Account *account in self.dataArray) { 72 | [tmpDateArray addObject:account.date]; 73 | tmpTotalMoney += [account.money doubleValue]; 74 | } 75 | 76 | self.totalMoney = tmpTotalMoney; 77 | 78 | NSSet *set = [NSSet setWithArray:[tmpDateArray copy]]; 79 | 80 | self.uniqueDateArray = [set sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:nil ascending:YES]]]; 81 | 82 | for (NSInteger i = 0; i < self.uniqueDateArray.count; i++) { 83 | // 将某一天的过滤出来 84 | NSArray *accountsInOneDay = [self.dataArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"date == %@", self.uniqueDateArray[i]]]; 85 | 86 | // 计算这一天金额总量 87 | double tmpTotalMoney = 0; 88 | for (Account *account in accountsInOneDay) { 89 | tmpTotalMoney += [account.money doubleValue]; 90 | } 91 | 92 | [tmpMoneyArray addObject:[NSNumber numberWithDouble:tmpTotalMoney]]; 93 | } 94 | 95 | self.uniqueMoneyArray = [tmpMoneyArray copy]; 96 | } 97 | 98 | - (void)setLabel { 99 | NSString *str; 100 | UIColor *color; 101 | // 支出用红色,收入用绿色 102 | if ([self.incomeType isEqualToString:@"income"]) { 103 | str = @"共收入:"; 104 | color = [UIColor blueColor]; 105 | } else { 106 | str = @"共支出:"; 107 | color = [UIColor redColor]; 108 | } 109 | 110 | NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ %@ %@ %@", self.date, self.type, str, [NSNumber numberWithDouble:self.totalMoney]]]; 111 | 112 | NSInteger formerStringLength = self.date.length + 2 + self.type.length + 2 + str.length + 1; 113 | 114 | [mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, formerStringLength)]; 115 | 116 | // 金额部分用color(不同颜色) 117 | [mutString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(formerStringLength, [NSString stringWithFormat:@"%@", [NSNumber numberWithDouble:self.totalMoney]].length)]; 118 | 119 | [self.moneyLabel setAttributedText:mutString]; 120 | } 121 | 122 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 123 | return self.uniqueDateArray.count; 124 | } 125 | 126 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 127 | AZXAllHistoryTableViewCell *cell = [self.typeTableView dequeueReusableCellWithIdentifier:@"typeDetailCell" forIndexPath:indexPath]; 128 | cell.date.text = self.uniqueDateArray[indexPath.row]; 129 | 130 | cell.money.text = [NSString stringWithFormat:@"%@", self.uniqueMoneyArray[indexPath.row]]; 131 | if ([self.incomeType isEqualToString:@"income"]) { 132 | cell.money.textColor = [UIColor blueColor]; 133 | } else { 134 | cell.money.textColor = [UIColor redColor]; 135 | } 136 | 137 | return cell; 138 | } 139 | 140 | 141 | #pragma mark - Navigation 142 | 143 | // In a storyboard-based application, you will often want to do a little preparation before navigation 144 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 145 | if ([segue.identifier isEqualToString:@"segueToDayDetail"]) { 146 | if ([[segue destinationViewController] isKindOfClass:[AZXAccountViewController class]]) { 147 | AZXAccountViewController *viewController = [segue destinationViewController]; 148 | 149 | NSIndexPath *indexPath = [self.typeTableView indexPathForSelectedRow]; 150 | 151 | viewController.passedDate = self.uniqueDateArray[indexPath.row]; 152 | viewController.selectedType = self.type; 153 | } 154 | } 155 | } 156 | 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /AZXTallyBook/Account+CoreDataProperties.h: -------------------------------------------------------------------------------- 1 | // 2 | // Account+CoreDataProperties.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/9. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | // Choose "Create NSManagedObject Subclass…" from the Core Data editor menu 9 | // to delete and recreate this implementation file for your updated model. 10 | // 11 | 12 | #import "Account.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface Account (CoreDataProperties) 17 | 18 | @property (nullable, nonatomic, retain) NSString *date; 19 | @property (nullable, nonatomic, retain) NSString *detail; 20 | @property (nullable, nonatomic, retain) NSString *incomeType; 21 | @property (nullable, nonatomic, retain) NSString *money; 22 | @property (nullable, nonatomic, retain) NSString *type; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /AZXTallyBook/Account+CoreDataProperties.m: -------------------------------------------------------------------------------- 1 | // 2 | // Account+CoreDataProperties.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/9. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | // Choose "Create NSManagedObject Subclass…" from the Core Data editor menu 9 | // to delete and recreate this implementation file for your updated model. 10 | // 11 | 12 | #import "Account+CoreDataProperties.h" 13 | 14 | @implementation Account (CoreDataProperties) 15 | 16 | @dynamic date; 17 | @dynamic detail; 18 | @dynamic incomeType; 19 | @dynamic money; 20 | @dynamic type; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /AZXTallyBook/Account.h: -------------------------------------------------------------------------------- 1 | // 2 | // Account.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/9. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface Account : NSManagedObject 15 | 16 | // Insert code here to declare functionality of your managed object subclass 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | 22 | #import "Account+CoreDataProperties.h" 23 | -------------------------------------------------------------------------------- /AZXTallyBook/Account.m: -------------------------------------------------------------------------------- 1 | // 2 | // Account.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/9. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "Account.h" 10 | 11 | @implementation Account 12 | 13 | // Insert code here to add functionality to your managed object subclass 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AZXTallyBook/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 17 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 18 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 19 | 20 | - (void)saveContext; 21 | - (NSURL *)applicationDocumentsDirectory; 22 | 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /AZXTallyBook/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | return YES; 20 | } 21 | 22 | - (void)applicationWillResignActive:(UIApplication *)application { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | 31 | // 退出应用时将appDidLaunch设为NO 32 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 33 | [defaults setBool:NO forKey:@"appDidLaunch"]; 34 | // 并保持CoreData的数据 35 | [self saveContext]; 36 | } 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application { 39 | // 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. 40 | } 41 | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application { 43 | // 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. 44 | } 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | // Saves changes in the application's managed object context before the application terminates. 49 | } 50 | 51 | #pragma mark - Core Data stack 52 | 53 | @synthesize managedObjectContext = _managedObjectContext; 54 | @synthesize managedObjectModel = _managedObjectModel; 55 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 56 | 57 | - (NSURL *)applicationDocumentsDirectory { 58 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.azxccmu.AZXTallyBook" in the application's documents directory. 59 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 60 | } 61 | 62 | - (NSManagedObjectModel *)managedObjectModel { 63 | // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 64 | if (_managedObjectModel != nil) { 65 | return _managedObjectModel; 66 | } 67 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"AZXTallyBook" withExtension:@"momd"]; 68 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 69 | return _managedObjectModel; 70 | } 71 | 72 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 73 | // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. 74 | if (_persistentStoreCoordinator != nil) { 75 | return _persistentStoreCoordinator; 76 | } 77 | 78 | // Create the coordinator and store 79 | 80 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 81 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"AZXTallyBook.sqlite"]; 82 | NSError *error = nil; 83 | NSString *failureReason = @"There was an error creating or loading the application's saved data."; 84 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 85 | // Report any error we got. 86 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 87 | dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 88 | dict[NSLocalizedFailureReasonErrorKey] = failureReason; 89 | dict[NSUnderlyingErrorKey] = error; 90 | error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 91 | // Replace this with code to handle the error appropriately. 92 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 93 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 94 | abort(); 95 | } 96 | 97 | return _persistentStoreCoordinator; 98 | } 99 | 100 | 101 | - (NSManagedObjectContext *)managedObjectContext { 102 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 103 | if (_managedObjectContext != nil) { 104 | return _managedObjectContext; 105 | } 106 | 107 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 108 | if (!coordinator) { 109 | return nil; 110 | } 111 | _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 112 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 113 | return _managedObjectContext; 114 | } 115 | 116 | #pragma mark - Core Data Saving support 117 | 118 | - (void)saveContext { 119 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 120 | if (managedObjectContext != nil) { 121 | NSError *error = nil; 122 | NSLog(@"saved"); 123 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 124 | // Replace this implementation with code to handle the error appropriately. 125 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 126 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 127 | abort(); 128 | } 129 | NSLog(@"saved"); 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "iconiPhoneSpootlight5_29pt@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "iconiPhoneSpootlight5_29pt@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "iconiPhoneSpootlight7_40pt@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "iconiPhoneSpootlight7_40pt@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "iconiPhoneApp_60pt@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "iconiPhoneApp_60pt@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "iconiPadSpootlight5_29pt.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "iconiPadSpootlight5_29pt@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "iconiPadSpootlight7_40pt.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "iconiPadSpootlight7_40pt@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "iconiPadApp_76pt.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "iconiPadApp_76pt@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "83.5x83.5", 77 | "idiom" : "ipad", 78 | "filename" : "iconiPadProApp_83.5pt@2x.png", 79 | "scale" : "2x" 80 | } 81 | ], 82 | "info" : { 83 | "version" : 1, 84 | "author" : "xcode" 85 | } 86 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadApp_76pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadApp_76pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadApp_76pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadApp_76pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadProApp_83.5pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadProApp_83.5pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight5_29pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight5_29pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight5_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight5_29pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight7_40pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight7_40pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight7_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPadSpootlight7_40pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneApp_60pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneApp_60pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneApp_60pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneApp_60pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight5_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight5_29pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight5_29pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight5_29pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight7_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight7_40pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight7_40pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/AppIcon.appiconset/iconiPhoneSpootlight7_40pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "交通路费.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "交通路费@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "交通路费@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/交通路费.imageset/交通路费@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "其他支出.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "其他支出@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "其他支出@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他支出.imageset/其他支出@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "其他收入.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "其他收入@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "其他收入@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/其他收入.imageset/其他收入@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "化妆护理.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "化妆护理@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "化妆护理@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/化妆护理.imageset/化妆护理@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "医疗体检.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "医疗体检@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "医疗体检@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/医疗体检.imageset/医疗体检@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "外出旅游.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "外出旅游@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "外出旅游@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/外出旅游.imageset/外出旅游@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "奖金福利.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "奖金福利@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "奖金福利@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/奖金福利.imageset/奖金福利@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "学习教育.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "学习教育@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "学习教育@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/学习教育.imageset/学习教育@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "工资薪酬.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "工资薪酬@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "工资薪酬@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/工资薪酬.imageset/工资薪酬@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "彩票中奖.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "彩票中奖@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "彩票中奖@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/彩票中奖.imageset/彩票中奖@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "慈善捐赠.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "慈善捐赠@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "慈善捐赠@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/慈善捐赠.imageset/慈善捐赠@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "房租水电.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "房租水电@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "房租水电@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/房租水电.imageset/房租水电@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "投资理财.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "投资理财@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "投资理财@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/投资理财.imageset/投资理财@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "日常用品.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "日常用品@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "日常用品@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/日常用品.imageset/日常用品@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "服装首饰.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "服装首饰@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "服装首饰@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/服装首饰.imageset/服装首饰@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "油费维护.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "油费维护@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "油费维护@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/油费维护.imageset/油费维护@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "游戏娱乐.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "游戏娱乐@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "游戏娱乐@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/游戏娱乐.imageset/游戏娱乐@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "烟酒消费.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "烟酒消费@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "烟酒消费@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/烟酒消费.imageset/烟酒消费@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "生意经营.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "生意经营@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "生意经营@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/生意经营.imageset/生意经营@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "电子产品.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "电子产品@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "电子产品@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/电子产品.imageset/电子产品@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "网上购物.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "网上购物@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "网上购物@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/网上购物.imageset/网上购物@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "运动健身.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "运动健身@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "运动健身@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/运动健身.imageset/运动健身@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "银行利息.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "银行利息@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "银行利息@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/银行利息.imageset/银行利息@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "餐饮食品.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "餐饮食品@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "餐饮食品@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/类别/餐饮食品.imageset/餐饮食品@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "统计25pt.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "统计25pt@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "统计25pt@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/统计.imageset/统计25pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "记账25pt.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "记账25pt@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "记账25pt@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/记账.imageset/记账25pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "设置25pt.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "设置25pt@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "设置25pt@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/设置.imageset/设置25pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "账本25pt.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "账本25pt@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "账本25pt@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt@2x.png -------------------------------------------------------------------------------- /AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/AZXTallyBook/Assets.xcassets/系统图标/账本.imageset/账本25pt@3x.png -------------------------------------------------------------------------------- /AZXTallyBook/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /AZXTallyBook/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | 简单记账 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIRequiresFullScreen 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /AZXTallyBook/UIViewController+BackButtonHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BackButtonHandler.h 3 | // 4 | // Created by Sergey Nikitenko on 10/1/13. 5 | // Copyright 2013 Sergey Nikitenko. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @protocol BackButtonHandlerProtocol 29 | @optional 30 | // Override this method in UIViewController derived class to handle 'Back' button click 31 | -(BOOL)navigationShouldPopOnBackButton; 32 | @end 33 | 34 | @interface UIViewController (BackButtonHandler) 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /AZXTallyBook/UIViewController+BackButtonHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BackButtonHandler.m 3 | // 4 | // Created by Sergey Nikitenko on 10/1/13. 5 | // Copyright 2013 Sergey Nikitenko. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import "UIViewController+BackButtonHandler.h" 27 | 28 | @implementation UIViewController (BackButtonHandler) 29 | 30 | @end 31 | 32 | @implementation UINavigationController (ShouldPopOnBackButton) 33 | 34 | - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { 35 | 36 | if([self.viewControllers count] < [navigationBar.items count]) { 37 | return YES; 38 | } 39 | 40 | BOOL shouldPop = YES; 41 | UIViewController* vc = [self topViewController]; 42 | if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) { 43 | shouldPop = [vc navigationShouldPopOnBackButton]; 44 | } 45 | 46 | if(shouldPop) { 47 | dispatch_async(dispatch_get_main_queue(), ^{ 48 | [self popViewControllerAnimated:YES]; 49 | }); 50 | } else { 51 | // Workaround for iOS7.1. Thanks to @boliva - http://stackoverflow.com/posts/comments/34452906 52 | for(UIView *subview in [navigationBar subviews]) { 53 | if(0. < subview.alpha && subview.alpha < 1.) { 54 | [UIView animateWithDuration:.25 animations:^{ 55 | subview.alpha = 1.; 56 | }]; 57 | } 58 | } 59 | } 60 | 61 | return NO; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /AZXTallyBook/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AZXTallyBook 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AZXTallyBookTests/AZXTallyBookTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXTallyBookTests.m 3 | // AZXTallyBookTests 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXTallyBookTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AZXTallyBookTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /AZXTallyBookTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /AZXTallyBookUITests/AZXTallyBookUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AZXTallyBookUITests.m 3 | // AZXTallyBookUITests 4 | // 5 | // Created by azx on 16/3/7. 6 | // Copyright © 2016年 azx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AZXTallyBookUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AZXTallyBookUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /AZXTallyBookUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, ‘8.0’ 2 | pod 'VENCalculatorInputView', '~> 1.5' 3 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - VENCalculatorInputView (1.5.4) 3 | 4 | DEPENDENCIES: 5 | - VENCalculatorInputView (~> 1.5) 6 | 7 | SPEC CHECKSUMS: 8 | VENCalculatorInputView: 988fa681ba6bb9b1f067842493bb622e80cc8da2 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Headers/Private/VENCalculatorInputView/NSString+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/NSString+VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Private/VENCalculatorInputView/UITextField+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/UITextField+VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Private/VENCalculatorInputView/VENCalculatorInputTextField.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputTextField.h -------------------------------------------------------------------------------- /Pods/Headers/Private/VENCalculatorInputView/VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Private/VENCalculatorInputView/VENMoneyCalculator.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENMoneyCalculator.h -------------------------------------------------------------------------------- /Pods/Headers/Public/VENCalculatorInputView/NSString+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/NSString+VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/VENCalculatorInputView/UITextField+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/UITextField+VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/VENCalculatorInputView/VENCalculatorInputTextField.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputTextField.h -------------------------------------------------------------------------------- /Pods/Headers/Public/VENCalculatorInputView/VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/VENCalculatorInputView/VENMoneyCalculator.h: -------------------------------------------------------------------------------- 1 | ../../../VENCalculatorInputView/VENCalculatorInputView/VENMoneyCalculator.h -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - VENCalculatorInputView (1.5.4) 3 | 4 | DEPENDENCIES: 5 | - VENCalculatorInputView (~> 1.5) 6 | 7 | SPEC CHECKSUMS: 8 | VENCalculatorInputView: 988fa681ba6bb9b1f067842493bb622e80cc8da2 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/azx.xcuserdatad/xcschemes/Pods.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/azx.xcuserdatad/xcschemes/VENCalculatorInputView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/azx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Pods.xcscheme 8 | 9 | isShown 10 | 11 | 12 | VENCalculatorInputView.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 31A846EE82314C5B4D4211BA818B8C30 21 | 22 | primary 23 | 24 | 25 | 98507F93374414A737B09BAE70974BE3 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## VENCalculatorInputView 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2014 Ayaka Nonaka 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of 11 | this software and associated documentation files (the "Software"), to deal in 12 | the Software without restriction, including without limitation the rights to 13 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 14 | the Software, and to permit persons to whom the Software is furnished to do so, 15 | subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 22 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 23 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | Generated by CocoaPods - http://cocoapods.org 28 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2014 Ayaka Nonaka 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy of 22 | this software and associated documentation files (the "Software"), to deal in 23 | the Software without restriction, including without limitation the rights to 24 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 25 | the Software, and to permit persons to whom the Software is furnished to do so, 26 | subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 33 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 34 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 35 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 | 38 | Title 39 | VENCalculatorInputView 40 | Type 41 | PSGroupSpecifier 42 | 43 | 44 | FooterText 45 | Generated by CocoaPods - http://cocoapods.org 46 | Title 47 | 48 | Type 49 | PSGroupSpecifier 50 | 51 | 52 | StringsTable 53 | Acknowledgements 54 | Title 55 | Acknowledgements 56 | 57 | 58 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | if [[ "$CONFIGURATION" == "Debug" ]]; then 61 | install_resource "VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace.png" 62 | install_resource "VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace@2x.png" 63 | install_resource "VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.xib" 64 | fi 65 | if [[ "$CONFIGURATION" == "Release" ]]; then 66 | install_resource "VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace.png" 67 | install_resource "VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace@2x.png" 68 | install_resource "VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.xib" 69 | fi 70 | 71 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 72 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 73 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 74 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 75 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 76 | fi 77 | rm -f "$RESOURCES_TO_COPY" 78 | 79 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 80 | then 81 | case "${TARGETED_DEVICE_FAMILY}" in 82 | 1,2) 83 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 84 | ;; 85 | 1) 86 | TARGET_DEVICE_ARGS="--target-device iphone" 87 | ;; 88 | 2) 89 | TARGET_DEVICE_ARGS="--target-device ipad" 90 | ;; 91 | *) 92 | TARGET_DEVICE_ARGS="--target-device mac" 93 | ;; 94 | esac 95 | 96 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 97 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 98 | while read line; do 99 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 100 | XCASSET_FILES+=("$line") 101 | fi 102 | done <<<"$OTHER_XCASSETS" 103 | 104 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 105 | fi 106 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/VENCalculatorInputView" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/VENCalculatorInputView" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"VENCalculatorInputView" 5 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/VENCalculatorInputView" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/VENCalculatorInputView" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"VENCalculatorInputView" 5 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/VENCalculatorInputView/VENCalculatorInputView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_VENCalculatorInputView : NSObject 3 | @end 4 | @implementation PodsDummy_VENCalculatorInputView 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/VENCalculatorInputView/VENCalculatorInputView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/VENCalculatorInputView/VENCalculatorInputView.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/VENCalculatorInputView" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/VENCalculatorInputView" 3 | PODS_ROOT = ${SRCROOT} 4 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ayaka Nonaka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/README.md: -------------------------------------------------------------------------------- 1 | VENCalculatorInputView 2 | ========= 3 | 4 | [![Build Status](https://travis-ci.org/venmo/VENCalculatorInputView.svg?branch=master)](https://travis-ci.org/venmo/VENCalculatorInputView) 5 | 6 | VENCalculatorInputView is the calculator keyboard that is used in the [Venmo](https://venmo.com/) iOS app. 7 | Available for iOS 6 and beyond. Enjoy. 8 | 9 | ![alt text](http://i.imgur.com/VWgymjH.gif "VENCalculatorInputView demo") 10 | 11 | Installation 12 | ---- 13 | 14 | The easiest way to get started is to use [CocoaPods](http://cocoapods.org/). Just add the following line to your Podfile: 15 | 16 | ```ruby 17 | pod 'VENCalculatorInputView', '~> 1.5' 18 | ``` 19 | 20 | Sample Usage 21 | ---- 22 | You can choose to use just ```VENCalculatorInputView``` (only the keyboard) and define your own behavior or use ```VENCalculatorInputTextField``` (keyboard + text field with money calculation built in). 23 | 24 | ### Using just the calculator keyboard 25 | 26 | #### 1. Set the input view. 27 | Find the ```UITextField``` or ```UITextView``` that you want to display the keyboard and set its ```inputView``` to an instance of ```VENCalculatorInputView```. 28 | 29 | ```obj-c 30 | myTextField.inputView = [VENCalculatorInputView new]; 31 | ``` 32 | 33 | This will have ```VENCalculatorInputView``` display when ```myTextField``` becomes ```firstResponder``` instead of the system keyboard. 34 | 35 | #### 2. Implement the `````` methods. 36 | 37 | First, have a class implement the `````` protocol and set ```myTextField.inputView.delegate``` to an instance of that class. 38 | 39 | Next, implement the delegate method that handles keyboard input: 40 | 41 | ```obj-c 42 | - (void)calculatorInputView:(VENCalculatorInputView *)inputView didTapKey:(NSString *)key { 43 | NSLog(@"Just tapped key: %@", key); 44 | // Handle the input. Something like [myTextField insertText:key]; 45 | } 46 | ``` 47 | 48 | Finally, implement the delegate method that handles the backspace key: 49 | 50 | ```obj-c 51 | - (void)calculatorInputViewDidTapBackspace:(VENCalculatorInputView *)calculatorInputView { 52 | NSLog(@"Just tapped backspace."); 53 | // Handle the backspace. Something like [myTextField deleteBackward]; 54 | } 55 | ``` 56 | 57 | Try it! 58 | 59 | You can read more about custom keyboards in [Apple’s documentation](https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/InputViews/InputViews.html). 60 | 61 | ### Using the calculator text field (optimized for money calculation) 62 | 63 | All you need to do is use ```VENCalculatorInputTextField``` instead of ```UITextField``` and use it like normal text field. It will automagically handle the input and make calculations. Take a look at out our ```VENCalculatorInputViewSample``` project. 64 | 65 | Localization 66 | ------ 67 | 68 | Different regions use different symbols as their decimal separator (e.g. ```.```, ```,```). By default, ```VENCalculatorInputView``` and ```VENCalculatorInputTextField``` use the current locale of the device. You can change it by setting the ```locale``` property. 69 | 70 | Testing 71 | ------ 72 | 73 | We’ve written some tests. You can run them by opening the project in Xcode and hitting `Command-U`. 74 | 75 | Contributing 76 | ------------ 77 | 78 | We’d love to see your ideas for improving this library! The best way to contribute is by submitting a pull request. We’ll do our best to respond to your patch as soon as possible. You can also submit a [new GitHub issue](https://github.com/venmo/VENCalculatorInputView/issues/new) if you find bugs or have questions. :octocat: 79 | 80 | Please make sure to follow our general coding style and add test coverage for new features! 81 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/Pods/VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace.png -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/Pods/VENCalculatorInputView/VENCalculatorInputView/Images/VENCalculatorIconBackspace@2x.png -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/NSString+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSString (VENCalculatorInputView) 4 | 5 | - (NSString *)stringByReplacingCharactersInSet:(NSCharacterSet *)characterSet 6 | withString:(NSString *)string; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/NSString+VENCalculatorInputView.m: -------------------------------------------------------------------------------- 1 | #import "NSString+VENCalculatorInputView.h" 2 | 3 | @implementation NSString (VENCalculatorInputView) 4 | 5 | - (NSString *)stringByReplacingCharactersInSet:(NSCharacterSet *)characterSet 6 | withString:(NSString *)string 7 | { 8 | return [[self componentsSeparatedByCharactersInSet:characterSet] componentsJoinedByString:string]; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/UITextField+VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UITextField (VENCalculatorInputView) 4 | 5 | - (NSRange)selectedNSRange; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/UITextField+VENCalculatorInputView.m: -------------------------------------------------------------------------------- 1 | #import "UITextField+VENCalculatorInputView.h" 2 | 3 | @implementation UITextField (VENCalculatorInputView) 4 | 5 | - (NSRange)selectedNSRange 6 | { 7 | UITextPosition *beginning = self.beginningOfDocument; 8 | 9 | UITextRange *selectedRange = self.selectedTextRange; 10 | UITextPosition *selectionStart = selectedRange.start; 11 | UITextPosition *selectionEnd = selectedRange.end; 12 | 13 | NSInteger location = [self offsetFromPosition:beginning toPosition:selectionStart]; 14 | NSInteger length = [self offsetFromPosition:selectionStart toPosition:selectionEnd]; 15 | 16 | return NSMakeRange(location, length); 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputTextField.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "VENCalculatorInputView.h" 3 | 4 | @interface VENCalculatorInputTextField : UITextField 5 | 6 | /** 7 | The locale to use for the decimal separator. 8 | Defaults to locale for current device. 9 | */ 10 | @property (strong, nonatomic) NSLocale *locale; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputTextField.m: -------------------------------------------------------------------------------- 1 | #import "VENCalculatorInputTextField.h" 2 | #import "VENMoneyCalculator.h" 3 | #import "UITextField+VENCalculatorInputView.h" 4 | 5 | @interface VENCalculatorInputTextField () 6 | @property (strong, nonatomic) VENMoneyCalculator *moneyCalculator; 7 | @end 8 | 9 | @implementation VENCalculatorInputTextField 10 | 11 | - (id)initWithFrame:(CGRect)frame { 12 | self = [super initWithFrame:frame]; 13 | if (self) { 14 | [self setUpInit]; 15 | } 16 | return self; 17 | } 18 | 19 | - (void)awakeFromNib { 20 | [self setUpInit]; 21 | } 22 | 23 | - (void)setUpInit { 24 | self.locale = [NSLocale currentLocale]; 25 | 26 | VENCalculatorInputView *inputView = [VENCalculatorInputView new]; 27 | inputView.delegate = self; 28 | inputView.locale = self.locale; 29 | self.inputView = inputView; 30 | 31 | VENMoneyCalculator *moneyCalculator = [VENMoneyCalculator new]; 32 | moneyCalculator.locale = self.locale; 33 | self.moneyCalculator = moneyCalculator; 34 | 35 | [self addTarget:self action:@selector(venCalculatorTextFieldDidEndEditing) forControlEvents:UIControlEventEditingDidEnd]; 36 | } 37 | 38 | 39 | #pragma mark - Properties 40 | 41 | - (void)setLocale:(NSLocale *)locale { 42 | _locale = locale; 43 | VENCalculatorInputView *inputView = (VENCalculatorInputView *)self.inputView; 44 | inputView.locale = locale; 45 | self.moneyCalculator.locale = locale; 46 | } 47 | 48 | 49 | #pragma mark - UITextField 50 | 51 | - (void)venCalculatorTextFieldDidEndEditing { 52 | NSString *textToEvaluate = [self trimExpressionString:self.text]; 53 | NSString *evaluatedString = [self.moneyCalculator evaluateExpression:textToEvaluate]; 54 | if (evaluatedString) { 55 | self.text = evaluatedString; 56 | } 57 | } 58 | 59 | 60 | #pragma mark - VENCalculatorInputViewDelegate 61 | 62 | - (void)calculatorInputView:(VENCalculatorInputView *)inputView didTapKey:(NSString *)key { 63 | if ([self.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) { 64 | NSRange range = [self selectedNSRange]; 65 | if (![self.delegate textField:self shouldChangeCharactersInRange:range replacementString:key]) { 66 | return; 67 | } 68 | } 69 | 70 | [self insertText:key]; 71 | NSString *subString = [self.text substringToIndex:self.text.length - 1]; 72 | if ([key isEqualToString:@"+"] || 73 | [key isEqualToString:@"−"] || 74 | [key isEqualToString:@"×"] || 75 | [key isEqualToString:@"÷"]) { 76 | NSString *evaluatedString = [self.moneyCalculator evaluateExpression:[self trimExpressionString:subString]]; 77 | if (evaluatedString) { 78 | self.text = [NSString stringWithFormat:@"%@%@", evaluatedString, key]; 79 | } else { 80 | self.text = subString; 81 | } 82 | } else if ([key isEqualToString:[self decimalSeparator]]) { 83 | NSString *secondToLastCharacterString = [self.text substringWithRange:NSMakeRange([self.text length] - 2, 1)]; 84 | if ([secondToLastCharacterString isEqualToString:[self decimalSeparator]]) { 85 | self.text = subString; 86 | } 87 | } 88 | } 89 | 90 | - (void)calculatorInputViewDidTapBackspace:(VENCalculatorInputView *)calculatorInputView { 91 | [self deleteBackward]; 92 | } 93 | 94 | 95 | #pragma mark - Helpers 96 | 97 | /** 98 | Removes any trailing operations and decimals. 99 | @param expressionString The expression string to trim 100 | @return The trimmed expression string 101 | */ 102 | - (NSString *)trimExpressionString:(NSString *)expressionString { 103 | NSString *txt = self.text; 104 | while ([txt length] > 0) { 105 | NSString *lastCharacterString = [txt substringFromIndex:[txt length] - 1]; 106 | if ([lastCharacterString isEqualToString:@"+"] || 107 | [lastCharacterString isEqualToString:@"−"] || 108 | [lastCharacterString isEqualToString:@"×"] || 109 | [lastCharacterString isEqualToString:@"÷"] || 110 | [lastCharacterString isEqualToString:self.decimalSeparator]) { 111 | txt = [txt substringToIndex:txt.length - 1]; 112 | } 113 | else { 114 | break; 115 | } 116 | } 117 | return txt; 118 | } 119 | 120 | - (NSString *)decimalSeparator { 121 | return [self.locale objectForKey:NSLocaleDecimalSeparator]; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class VENCalculatorInputView; 4 | @protocol VENCalculatorInputViewDelegate 5 | 6 | @optional 7 | - (void)calculatorInputView:(VENCalculatorInputView *)inputView didTapKey:(NSString *)key; 8 | - (void)calculatorInputViewDidTapBackspace:(VENCalculatorInputView *)calculatorInputView; 9 | 10 | @end 11 | 12 | @interface VENCalculatorInputView : UIView 13 | 14 | @property (weak, nonatomic) id delegate; 15 | 16 | /**----------------------------------------------------------------------------- 17 | * @name Localization 18 | * ----------------------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | The locale to use for the decimal separator. 23 | Defaults to locale for current device. 24 | */ 25 | @property (strong, nonatomic) NSLocale *locale; 26 | 27 | 28 | /**----------------------------------------------------------------------------- 29 | * @name Customizing colors 30 | * ----------------------------------------------------------------------------- 31 | */ 32 | 33 | @property (strong, nonatomic) UIColor *buttonTitleColor; 34 | @property (strong, nonatomic) UIFont *buttonTitleFont; 35 | @property (strong, nonatomic) UIColor *buttonHighlightedColor; 36 | 37 | @property (strong, nonatomic) UIColor *numberButtonBackgroundColor; 38 | @property (strong, nonatomic) UIColor *numberButtonBorderColor; 39 | 40 | @property (strong, nonatomic) UIColor *operationButtonBackgroundColor; 41 | @property (strong, nonatomic) UIColor *operationButtonBorderColor; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENCalculatorInputView.m: -------------------------------------------------------------------------------- 1 | #import "VENCalculatorInputView.h" 2 | 3 | @interface VENCalculatorInputView () 4 | 5 | @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *numberButtonCollection; 6 | @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *operationButtonCollection; 7 | @property (strong, nonatomic) IBOutlet UIButton *decimalButton; 8 | 9 | @end 10 | 11 | @implementation VENCalculatorInputView 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | self = [[[NSBundle bundleForClass:[self class]] loadNibNamed:@"VENCalculatorInputView" owner:self options:nil] firstObject]; 15 | if (self) { 16 | // Set default locale 17 | self.locale = [NSLocale currentLocale]; 18 | 19 | // Set customizable properties 20 | [self setNumberButtonBackgroundColor:[UIColor colorWithWhite:0.98828 alpha:1]]; 21 | [self setNumberButtonBorderColor:[UIColor colorWithRed:193/255.0f green:195/255.0f blue:199/255.0f alpha:1]]; 22 | [self setOperationButtonBackgroundColor:[UIColor colorWithRed:193/255.0f green:196/255.0f blue:200/255.0f alpha:1]]; 23 | [self setOperationButtonBorderColor:[UIColor colorWithRed:172/255.0f green:174/255.0f blue:177/255.0f alpha:1]]; 24 | [self setButtonHighlightedColor:[UIColor grayColor]]; 25 | [self setButtonTitleColor:[UIColor darkTextColor]]; 26 | 27 | // Set default properties 28 | for (UIButton *numberButton in self.numberButtonCollection) { 29 | [self setupButton:numberButton]; 30 | } 31 | for (UIButton *operationButton in self.operationButtonCollection) { 32 | [self setupButton:operationButton]; 33 | } 34 | } 35 | return self; 36 | } 37 | 38 | - (void)setLocale:(NSLocale *)locale { 39 | _locale = locale; 40 | NSString *decimalSymbol = [locale objectForKey:NSLocaleDecimalSeparator]; 41 | [self.decimalButton setTitle:decimalSymbol forState:UIControlStateNormal]; 42 | } 43 | 44 | - (void)setupButton:(UIButton *)button { 45 | button.layer.borderWidth = 0.25f; 46 | } 47 | 48 | - (IBAction)userDidTapBackspace:(UIButton *)sender { 49 | [[UIDevice currentDevice] playInputClick]; 50 | if ([self.delegate respondsToSelector:@selector(calculatorInputViewDidTapBackspace:)]) { 51 | [self.delegate calculatorInputViewDidTapBackspace:self]; 52 | } 53 | } 54 | 55 | - (IBAction)userDidTapKey:(UIButton *)sender { 56 | [[UIDevice currentDevice] playInputClick]; 57 | if ([self.delegate respondsToSelector:@selector(calculatorInputView:didTapKey:)]) { 58 | [self.delegate calculatorInputView:self didTapKey:sender.titleLabel.text]; 59 | } 60 | } 61 | 62 | 63 | #pragma mark - UIInputViewAudioFeedback 64 | 65 | - (BOOL)enableInputClicksWhenVisible { 66 | return YES; 67 | } 68 | 69 | 70 | #pragma mark - Helpers 71 | 72 | - (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size { 73 | UIGraphicsBeginImageContextWithOptions(size, NO, 0); 74 | CGContextRef context = UIGraphicsGetCurrentContext(); 75 | 76 | [color set]; 77 | CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height)); 78 | 79 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 80 | UIGraphicsEndImageContext(); 81 | return image; 82 | } 83 | 84 | 85 | #pragma mark - Properties 86 | 87 | - (void)setButtonTitleColor:(UIColor *)buttonTitleColor { 88 | _buttonTitleColor = buttonTitleColor; 89 | for (UIButton *numberButton in self.numberButtonCollection) { 90 | [numberButton setTitleColor:buttonTitleColor forState:UIControlStateNormal]; 91 | } 92 | for (UIButton *operationButton in self.operationButtonCollection) { 93 | [operationButton setTitleColor:buttonTitleColor forState:UIControlStateNormal]; 94 | } 95 | } 96 | 97 | - (void)setButtonTitleFont:(UIFont *)buttonTitleFont { 98 | _buttonTitleFont = buttonTitleFont; 99 | for (UIButton *numberButton in self.numberButtonCollection) { 100 | numberButton.titleLabel.font = buttonTitleFont; 101 | } 102 | for (UIButton *operationButton in self.operationButtonCollection) { 103 | operationButton.titleLabel.font = buttonTitleFont; 104 | } 105 | } 106 | 107 | - (void)setButtonHighlightedColor:(UIColor *)buttonHighlightedColor { 108 | _buttonHighlightedColor = buttonHighlightedColor; 109 | for (UIButton *numberButton in self.numberButtonCollection) { 110 | [numberButton setBackgroundImage:[self imageWithColor:buttonHighlightedColor size:CGSizeMake(50, 50)] 111 | forState:UIControlStateHighlighted]; 112 | } 113 | for (UIButton *operationButton in self.operationButtonCollection) { 114 | [operationButton setBackgroundImage:[self imageWithColor:buttonHighlightedColor size:CGSizeMake(50, 50)] 115 | forState:UIControlStateHighlighted]; 116 | } 117 | } 118 | 119 | - (void)setNumberButtonBackgroundColor:(UIColor *)numberButtonBackgroundColor { 120 | _numberButtonBackgroundColor = numberButtonBackgroundColor; 121 | for (UIButton *numberButton in self.numberButtonCollection) { 122 | numberButton.backgroundColor = numberButtonBackgroundColor; 123 | } 124 | } 125 | 126 | - (void)setNumberButtonBorderColor:(UIColor *)numberButtonBorderColor { 127 | _numberButtonBorderColor = numberButtonBorderColor; 128 | for (UIButton *numberButton in self.numberButtonCollection) { 129 | numberButton.layer.borderColor = numberButtonBorderColor.CGColor; 130 | } 131 | } 132 | 133 | - (void)setOperationButtonBackgroundColor:(UIColor *)operationButtonBackgroundColor { 134 | _operationButtonBackgroundColor = operationButtonBackgroundColor; 135 | for (UIButton *operationButton in self.operationButtonCollection) { 136 | operationButton.backgroundColor = operationButtonBackgroundColor; 137 | } 138 | } 139 | 140 | - (void)setOperationButtonBorderColor:(UIColor *)operationButtonBorderColor { 141 | _operationButtonBorderColor = operationButtonBorderColor; 142 | for (UIButton *operationButton in self.operationButtonCollection) { 143 | operationButton.layer.borderColor = operationButtonBorderColor.CGColor; 144 | } 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENMoneyCalculator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface VENMoneyCalculator : NSObject 4 | 5 | @property (strong, nonatomic) NSLocale *locale; 6 | 7 | /** 8 | * Evaluates a mathematical expression containing +, −, ×, and ÷. 9 | * @param expression The expression to evaluate 10 | * @return The evaluated expression. Returns nil if the expression is invalid. 11 | */ 12 | - (NSString *)evaluateExpression:(NSString *)expression; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Pods/VENCalculatorInputView/VENCalculatorInputView/VENMoneyCalculator.m: -------------------------------------------------------------------------------- 1 | #import "VENMoneyCalculator.h" 2 | #import "NSString+VENCalculatorInputView.h" 3 | 4 | @interface VENMoneyCalculator () 5 | @property (strong, nonatomic) NSNumberFormatter *numberFormatter; 6 | @end 7 | 8 | @implementation VENMoneyCalculator 9 | 10 | - (instancetype)init { 11 | self = [super init]; 12 | if (self) { 13 | self.locale = [NSLocale currentLocale]; 14 | } 15 | return self; 16 | } 17 | 18 | - (NSString *)evaluateExpression:(NSString *)expressionString { 19 | if (!expressionString) { 20 | return nil; 21 | } 22 | NSString *sanitizedString = [self sanitizedString:expressionString]; 23 | NSString *floatString = [NSString stringWithFormat:@"1.0*%@", sanitizedString]; 24 | NSExpression *expression; 25 | id result; 26 | @try { 27 | expression = [NSExpression expressionWithFormat:floatString]; 28 | result = [expression expressionValueWithObject:nil context:nil]; 29 | } 30 | @catch (NSException *exception) { 31 | if ([[exception name] isEqualToString:NSInvalidArgumentException]) { 32 | return nil; 33 | } else { 34 | [exception raise]; 35 | } 36 | } 37 | if ([result isKindOfClass:[NSNumber class]]) { 38 | NSInteger integerExpression = [(NSNumber *)result integerValue]; 39 | CGFloat floatExpression = [(NSNumber *)result floatValue]; 40 | if (integerExpression == floatExpression) { 41 | return [(NSNumber *)result stringValue]; 42 | } else if (floatExpression >= CGFLOAT_MAX || floatExpression <= CGFLOAT_MIN || isnan(floatExpression)) { 43 | return @"0"; 44 | } else { 45 | NSString *moneyFormattedNumber = [[self numberFormatter] stringFromNumber:@(floatExpression)]; 46 | return [moneyFormattedNumber stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 47 | } 48 | } else { 49 | return nil; 50 | } 51 | } 52 | 53 | - (void)setLocale:(NSLocale *)locale { 54 | _locale = locale; 55 | self.numberFormatter.locale = locale; 56 | } 57 | 58 | 59 | #pragma mark - Private 60 | 61 | - (NSNumberFormatter *)numberFormatter { 62 | if (!_numberFormatter) { 63 | _numberFormatter = [NSNumberFormatter new]; 64 | [_numberFormatter setLocale:self.locale]; 65 | [_numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 66 | [_numberFormatter setCurrencySymbol:@""]; 67 | } 68 | return _numberFormatter; 69 | } 70 | 71 | - (NSString *)sanitizedString:(NSString *)string { 72 | NSString *groupingSeperator = [self.locale objectForKey:NSLocaleGroupingSeparator]; 73 | NSString *withoutGroupingSeperator = [string stringByReplacingOccurrencesOfString:groupingSeperator withString:@""]; 74 | return [[self replaceOperandsInString:withoutGroupingSeperator] stringByReplacingCharactersInSet:[self illegalCharacters] withString:@""]; 75 | } 76 | 77 | - (NSString *)replaceOperandsInString:(NSString *)string { 78 | NSString *subtractReplaced = [string stringByReplacingOccurrencesOfString:@"−" withString:@"-"]; 79 | NSString *divideReplaced = [subtractReplaced stringByReplacingOccurrencesOfString:@"÷" withString:@"/"]; 80 | NSString *multiplyReplaced = [divideReplaced stringByReplacingOccurrencesOfString:@"×" withString:@"*"]; 81 | 82 | return [multiplyReplaced stringByReplacingOccurrencesOfString:[self decimalSeparator] withString:@"."]; 83 | } 84 | 85 | - (NSCharacterSet *)illegalCharacters { 86 | return [[NSCharacterSet characterSetWithCharactersInString:@"0123456789-/*.+"] invertedSet]; 87 | } 88 | 89 | - (NSString *)decimalSeparator { 90 | return [self.locale objectForKey:NSLocaleDecimalSeparator]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AZXTallyBook 2 | 简单记账 -- 已在AppStore上线 3 | 下载地址:https://itunes.apple.com/cn/app/jian-dan-ji-zhang-si-ren-zhang/id1095015625?mt=8 4 | 主要用CoreData实现数据的持久本地化保存 5 | 应用特点: 6 | - 极速记账,5秒钟记下一笔帐 7 | - 饼状图统计月收入支出,钱花在哪里一目了然 8 | - 支持自定义收入支持类别,自定义图片 9 | - 支持密码保护,保护您的个人隐私 10 | - 历史记录查询每一笔支出,汇总每月结余,清楚掌握财产动态 11 | 12 | 屏幕截图: 13 | ![首页](http://upload-images.jianshu.io/upload_images/1776120-c6bfac40e87906f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 14 | 15 | ![统计](http://upload-images.jianshu.io/upload_images/1776120-63e48676282dd555.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 16 | 17 | ![设置](http://upload-images.jianshu.io/upload_images/1776120-b36c9f9b520d570c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 18 | -------------------------------------------------------------------------------- /screenshots/4.7_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/screenshots/4.7_1.png -------------------------------------------------------------------------------- /screenshots/4.7_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/screenshots/4.7_2.png -------------------------------------------------------------------------------- /screenshots/4.7_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XinStar1/AZXTallyBook/2fa89a4d1c1a3f07a3c2e7c99304b3f4e413ab67/screenshots/4.7_3.png --------------------------------------------------------------------------------