ScreenshotiOS IBOutlet UILabel Duplicate
在截圖中,fork和knife之後的標籤呈現兩次。以下代碼中的標籤爲budgetLabel。只需將IBOutlet添加到故事板中的標籤,而不是在代碼中創建。這是怎麼發生的?我不知道。
//
// LogViewController.m
// Calorie
//
// Created by 但 江 on 13-12-8.
// Copyright (c) 2013年 Dan Thought Studio. All rights reserved.
//
#import "DTLogsViewController.h"
#import "DTAlertView.h"
#import "DTBlankView.h"
#import "DTCircleView.h"
#import "DTCalendarHeader.h"
#import "DTLogHeader.h"
#import "DTLogCell.h"
#import "DTRectangleView.h"
#import "DTPercentView.h"
#import "DTTheme.h"
#import "DTUserDefaults.h"
#import "DTDataManager.h"
#import "DTUnitConverter.h"
#import "DTContextObserver.h"
#import "NSDate+Extend.h"
#import "DTDevice.h"
#import "DTConstant.h"
#import "DTLog.h"
static NSString * const DTLogHeaderIdentifier = @"LogHeader";
static NSString * const DTLogCellIdentifier = @"LogCell";
static NSString * const DTCalendarCellIdentifier = @"CalendarCell";
@interface DTLogsViewController() <UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, DTContextObserverDelegate>
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *burnCircleLeading;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *burnCircleTrailing;
@property (nonatomic, weak) IBOutlet DTCircleView *intakeCircleView;
@property (nonatomic, weak) IBOutlet DTCircleView *burnCircleView;
@property (nonatomic, weak) IBOutlet DTCircleView *netCircleView;
@property (nonatomic, weak) IBOutlet UILabel *intakeLabel;
@property (nonatomic, weak) IBOutlet UILabel *burnLabel;
@property (nonatomic, weak) IBOutlet UILabel *netLabel;
@property (nonatomic, weak) IBOutlet UILabel *intakeUnit;
@property (nonatomic, weak) IBOutlet UILabel *burnUnit;
@property (nonatomic, weak) IBOutlet UILabel *netUnit;
@property (nonatomic, weak) IBOutlet UILabel *dayLabel;
@property (nonatomic, weak) IBOutlet UIImageView *budgetImageView;
@property (nonatomic, weak) IBOutlet UILabel *budgetLabel;
@property (nonatomic, weak) IBOutlet UILabel *recommendLabel;
@property (nonatomic, weak) IBOutlet DTPercentView *percentView;
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet DTCalendarHeader *calendarHeader;
@property (nonatomic, weak) IBOutlet UICollectionView *collectionView;
@property (nonatomic, strong) DTBlankView *blankView;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, copy) NSArray *brands;
@property (nonatomic, strong) DTContextObserver *observer;
@property (nonatomic) CGFloat calendarCellWidth;
@property (nonatomic) CGFloat calendarCellSpace;
@end
@implementation DTLogsViewController
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:DTPersistentStoreIsReadyNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:DTUserDefaultsOnlyUnitChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:DTUserDefaultsExcludeUnitChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationSignificantTimeChangeNotification object:[UIApplication sharedApplication]];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.tabBarItem.selectedImage = [UIImage imageNamed:@"notepad-full"];
self.date = [NSDate new];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(initDatas) name:DTPersistentStoreIsReadyNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsChanged) name:DTUserDefaultsOnlyUnitChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsChanged) name:DTUserDefaultsExcludeUnitChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(significantTimeChanged) name:UIApplicationSignificantTimeChangeNotification object:[UIApplication sharedApplication]];
UIBarButtonItem *calendarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"calendar-normal"] style:UIBarButtonItemStylePlain target:self action:@selector(calendar)];
UIBarButtonItem *tomorrowButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"right-arrow-line"] style:UIBarButtonItemStylePlain target:self action:@selector(tomorrow)];
UIBarButtonItem *yesterdayButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"left-arrow-line"] style:UIBarButtonItemStylePlain target:self action:@selector(yesterday)];
UIBarButtonItem *todayButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BackToToday", @"Back To Today Text") style:UIBarButtonItemStylePlain target:self action:@selector(today)];
self.navigationItem.leftBarButtonItem = calendarButtonItem;
self.navigationItem.rightBarButtonItems = @[tomorrowButtonItem, yesterdayButtonItem, todayButtonItem];
self.intakeCircleView.color = [DTTheme orangeColor];
self.burnCircleView.color = [DTTheme greenColor];
self.netCircleView.color = [DTTheme purpleColor];
self.percentView.color = [DTTheme purpleColor];
[self.tableView registerClass:[DTLogHeader class] forHeaderFooterViewReuseIdentifier:DTLogHeaderIdentifier];
[self.tableView registerClass:[DTLogCell class] forCellReuseIdentifier:DTLogCellIdentifier];
self.calendarCellWidth = CalendarItemWidthPhoneOther;
self.calendarCellSpace = CalendarItemSpacePhoneOther;
if ([DTDevice isPhone6Plus]) {
self.calendarCellWidth = CalendarItemWidthPhone6Plus;
self.calendarCellSpace = CalendarItemSpacePhone6Plus;
} else if ([DTDevice isPhone6]) {
self.calendarCellWidth = CalendarItemWidthPhone6;
self.calendarCellSpace = CalendarItemSpacePhone6;
} else if ([DTDevice isPadPortrait]) {
self.calendarCellWidth = CalendarItemWidthPadPortrait;
self.calendarCellSpace = CalendarItemSpacePadPortrait;
} else if ([DTDevice isPadLandscape]) {
self.calendarCellWidth = CalendarItemWidthPadLandscape;
self.calendarCellSpace = CalendarItemSpacePadLandscape;
}
[self.calendarHeader.previousMonthButton removeTarget:self action:@selector(previousMonth) forControlEvents:UIControlEventTouchUpInside];
[self.calendarHeader.previousMonthButton addTarget:self action:@selector(previousMonth) forControlEvents:UIControlEventTouchUpInside];
[self.calendarHeader.nextMonthButton removeTarget:self action:@selector(nextMonth) forControlEvents:UIControlEventTouchUpInside];
[self.calendarHeader.nextMonthButton addTarget:self action:@selector(nextMonth) forControlEvents:UIControlEventTouchUpInside];
self.tableView.hidden = NO;
self.calendarHeader.hidden = YES;
self.collectionView.hidden = YES;
if ([DTDataManager sharedInstance].status == DTDataManagerStatusPersistentStoreIsReady) {
[self initDatas];
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
CGFloat width = CGRectGetWidth(self.view.frame);
CGFloat burnCircleSpace = (width - CGRectGetWidth(self.burnCircleView.frame) * 3)/4;
self.burnCircleLeading.constant = burnCircleSpace;
self.burnCircleTrailing.constant = burnCircleSpace;
[self.calendarHeader reloadWithWidth:width weekdayWidth:self.calendarCellWidth weekdaySpace:self.calendarCellSpace];
if ([DTUserDefaults getAge] == 0) {
[self performSegueWithIdentifier:@"LogToWelcome" sender:self];
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) {
self.calendarCellWidth = CalendarItemWidthPadPortrait;
self.calendarCellSpace = CalendarItemSpacePadPortrait;
} else {
self.calendarCellWidth = CalendarItemWidthPadLandscape;
self.calendarCellSpace = CalendarItemSpacePadLandscape;
}
CGFloat width = CGRectGetWidth(self.view.frame);
CGFloat burnCircleSpace = (width - CGRectGetWidth(self.burnCircleView.frame) * 3)/4;
self.burnCircleLeading.constant = burnCircleSpace;
self.burnCircleTrailing.constant = burnCircleSpace;
[self.calendarHeader reloadWithWidth:width weekdayWidth:self.calendarCellWidth weekdaySpace:self.calendarCellSpace];
[self.collectionView reloadData];
self.blankView.frame = CGRectMake(0, self.topLayoutGuide.length, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - self.topLayoutGuide.length - self.bottomLayoutGuide.length);
}
#pragma mark - Collection View Data Source and Delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSDate *firstDayOfMonth = [self.date firstDayOfMonth];
NSInteger offset = [firstDayOfMonth weekday] - 1;
NSInteger numberOfDaysInMonth = [firstDayOfMonth numberOfDaysInMonth];
return offset + numberOfDaysInMonth;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:DTCalendarCellIdentifier forIndexPath:indexPath];
NSDate *firstDayOfMonth = [self.date firstDayOfMonth];
NSInteger offset = [firstDayOfMonth weekday] - 1;
if (indexPath.row < offset) {
cell.hidden = YES;
} else {
cell.hidden = NO;
NSInteger day = indexPath.row + 1 - offset;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dayOfMonthComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:firstDayOfMonth];
[dayOfMonthComponents setDay:day];
NSDate *dayOfMonth = [calendar dateFromComponents:dayOfMonthComponents];
UILabel *label = cell.contentView.subviews[0];
UIImageView *imageView = cell.contentView.subviews[1];
UIColor *labelTextColor;
UIColor *cellBackgroundColor;
if ([dayOfMonth sameDay:self.date]) {
labelTextColor = [UIColor whiteColor];
cellBackgroundColor = [DTTheme calendarCurrentDateColor];
} else if ([dayOfMonth sameDay:[NSDate new]]) {
labelTextColor = [UIColor whiteColor];
cellBackgroundColor = [DTTheme orangeColor];
} else {
labelTextColor = [DTTheme darkGrayColor];
cellBackgroundColor = [DTTheme calendarDefaultDateColor];
}
label.textColor = labelTextColor;
cell.backgroundColor = cellBackgroundColor;
label.text = [dayOfMonth formatDate:@"d"];
if ([[DTDataManager sharedInstance] existedLogsWithDate:[dayOfMonth formatDayOfYear]]) {
imageView.hidden = NO;
imageView.tintColor = labelTextColor;
imageView.image = [[UIImage imageNamed:@"circle-full"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
} else {
imageView.hidden = YES;
}
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(self.calendarCellWidth, self.calendarCellWidth);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return self.calendarCellSpace;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return self.calendarCellSpace;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
CGFloat padding = (CGRectGetWidth(self.view.frame) - self.calendarCellWidth * 7 - self.calendarCellSpace * 6)/2;
return UIEdgeInsetsMake(0, padding, padding, padding);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDate *firstDayOfMonth = [self.date firstDayOfMonth];
NSInteger offset = [firstDayOfMonth weekday] - 1;
if (indexPath.row >= offset) {
NSInteger day = indexPath.row + 1 - offset;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dayOfMonthComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:firstDayOfMonth];
[dayOfMonthComponents setDay:day];
self.date = [calendar dateFromComponents:dayOfMonthComponents];
[self initDatas];
}
}
#pragma mark - Table View Data Source and Delegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.brands.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *logs = self.brands[section];
return logs.count;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
DTLogHeader *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:DTLogHeaderIdentifier];
NSArray *logs = self.brands[section];
DTLog *log = logs.firstObject;
if ([log isNoBrand]) {
header.contentTitleLabel.text = NSLocalizedString(@"NoBrand", @"No Brand Text");
} else {
header.contentTitleLabel.text = log.brand;
}
return header;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DTLogCell *cell = [tableView dequeueReusableCellWithIdentifier:DTLogCellIdentifier];
NSArray *logs = self.brands[indexPath.section];
DTLog *log = logs[indexPath.row];
UIColor *color = log.isFood ? [DTTheme orangeColor] : [DTTheme greenColor];
NSString *modifier = log.isFood ? @"+" : @"-";
int calorie = [DTUserDefaults isUnitStandard] ? log.calorieStandard : log.calorieMetric;
((DTRectangleView *)cell.contentRectangleView).color = color;
cell.contentNameLabel.text = log.name;
cell.contentUnitLabel.text = log.unit;
cell.contentCalorieLabel.text = [NSString stringWithFormat:@"%@ %d %@", modifier, calorie, [DTUserDefaults calorieUnit]];
cell.contentCalorieLabel.textColor = color;
return cell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSArray *logs = self.brands[indexPath.section];
DTLog *log = logs[indexPath.row];
[[DTDataManager sharedInstance] removeLog:log];
}
}
#pragma mark - Actions
- (void)calendar {
if (self.tableView.hidden) {
self.tableView.hidden = NO;
self.calendarHeader.hidden = YES;
self.collectionView.hidden = YES;
} else {
self.tableView.hidden = YES;
self.calendarHeader.hidden = NO;
self.collectionView.hidden = NO;
}
}
- (void)today {
self.date = [NSDate new];
[self initDatas];
}
- (void)yesterday {
self.date = [self.date yesterday];
[self initDatas];
}
- (void)tomorrow {
self.date = [self.date tomorrow];
[self initDatas];
}
- (void)previousMonth {
self.date = [self.date previousMonth];
[self initDatas];
}
- (void)nextMonth {
self.date = [self.date nextMonth];
[self initDatas];
}
#pragma mark - ManagedObjectContextObserverDelegate
- (void)contextObserverDidInsert {
[self initDatas];
}
- (void)contextObserverDidDelete {
[self initDatas];
}
#pragma mark - Private Helper Method
- (void)initDatas {
NSString *date = [self.date formatDayOfYear];
NSMutableArray *brands = [NSMutableArray new];
NSArray *logObjects = [[DTDataManager sharedInstance] findLogsWithDate:date];
DTLog *lastLog;
NSMutableArray *logs;
for (NSManagedObject *logObject in logObjects) {
DTLog *log = [[DTLog alloc] initWithManagedObject:logObject];
if (!lastLog || ![lastLog.brand isEqual:log.brand]) {
logs = [NSMutableArray new];
[brands addObject:logs];
lastLog = log;
}
[logs addObject:log];
}
self.brands = brands;
[self reloadView];
if (self.observer) {
[[DTDataManager sharedInstance] resetLogContextObserver:self.observer date:date];
} else {
self.observer = [[DTDataManager sharedInstance] logContextObserverWithDate:date];
self.observer.delegate = self;
}
}
- (void)reloadView {
[self reloadTotal];
[self.tableView reloadData];
self.calendarHeader.monthLabel.text = [self.date localMonth];
[self.collectionView reloadData];
}
- (void)reloadTotal {
NSString *calorieUnit = [DTUserDefaults calorieUnit];
int recommend = [DTUnitConverter dailyIntake];
int intake = 0;
int burn = 0;
for (NSArray *logs in self.brands) {
for (DTLog *log in logs) {
int calorie = [DTUserDefaults isUnitStandard] ? log.calorieStandard : log.calorieMetric;
if (log.isFood) {
intake += calorie;
} else {
burn += calorie;
}
}
}
int neat = intake - burn;
int suggestion = recommend - neat;
NSString *imageName = @"utensils-full";
NSString *modifier = @"";
if (suggestion > 0) {
modifier = @"+";
} else if (suggestion < 0) {
imageName = @"weights-full";
}
CGFloat percent = neat * 1.0/recommend;
if (percent > 1.0) {
percent = 1.0;
}
self.intakeLabel.text = [NSString stringWithFormat:@"%d", intake];
self.burnLabel.text = [NSString stringWithFormat:@"%d", burn];
self.netLabel.text = [NSString stringWithFormat:@"%d", neat];
self.intakeUnit.text = calorieUnit;
self.burnUnit.text = calorieUnit;
self.netUnit.text = calorieUnit;
self.dayLabel.text = [NSString stringWithFormat:@"%@ %@", [self.date localDate], [self.date localWeekday]];
self.budgetImageView.image = [UIImage imageNamed:imageName];
self.budgetLabel.text = [NSString stringWithFormat:@"%@%d %@", modifier, suggestion, calorieUnit];
self.recommendLabel.text = [NSString stringWithFormat:@"%d %@", recommend, calorieUnit];
self.percentView.percent = percent;
}
- (void)userDefaultsChanged {
[self reloadView];
}
- (void)significantTimeChanged {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *currentTime = [NSDate new];
NSDate *significantTime = [DTUserDefaults getSignificantTime];
if (significantTime) {
NSDateComponents *currentTimeComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit)
fromDate:currentTime];
NSDateComponents *significantTimeComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit)
fromDate:significantTime];
if (significantTimeComponents.day != currentTimeComponents.day
|| significantTimeComponents.month != currentTimeComponents.month
|| significantTimeComponents.year != currentTimeComponents.year) {
self.date = [NSDate new];
[self initDatas];
[DTUserDefaults setSignificantTime:currentTime];
}
} else {
self.date = [NSDate new];
[self initDatas];
[DTUserDefaults setSignificantTime:currentTime];
}
}
@end
這個問題沒有足夠的信息。沒有任何問題的截圖或背景。 – 2015-02-06 02:07:07
你應該更多地寫下這個視圖控制器中發生的事情。 – 2015-02-06 02:09:08
我沒有足夠的聲望發佈圖片。這是一個[截圖鏈接](http://segmentfault.com/img/bVkOUY/view)。每次用戶更改日期以查看當天的總卡路里。它會在覈心數據中找到數據,然後調用reloadTotal來更新視圖。所以budgetLabel渲染兩次。 – 2015-02-06 02:43:05