Objective-Cで目覚ましを作成しました

Objective-Cで動作する iOS用の目覚ましを作成しました。

アラームが開始されると自動スリープが無効になります。また、UserDefaultsで起床時間を保持します。

下記よりソースコードのダウンロードが行えます。

ダウンロード

編集ファイル

  1. AppDelegate.h+m
  2. AlarmViewController.h+m
  3. Alarm-Info.plist (バックグラウンド再生のため、Required background modesの項目を追加)
  4. Alarm-Prefix.pch

ソースコード

Alarm-Prefix.pch

1
2
3
4
5
6
7
8
9
10
#import "AppDelegate.h"

#define APP_DELEGATE            (AppDelegate*)[[UIApplication sharedApplication] delegate]

NSUserDefaults *userDefaults;

#define UD_WAKE_UP_TIME_KEY     @"UD_WAKE_UP_TIME_KEY"
#define DEFAULT_WAKE_UP_TIME    @"08:00"

NSString   *wakeUpTime;

AppDelegate.h

1
2
3
4
5
#pragma mark property prototype
@property (strong, nonatomic) UIWindow *window;

#pragma mark method prototype
- (void)setIdleTimer:(BOOL)isDisabled;

AppDelegate.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //ユーザーデフォルト初期化
    userDefaults  = [NSUserDefaults standardUserDefaults];

    //設定適用
    [self initSettings];

    //ユーザーデフォルトの初回読み込みフラグ立てる
    [self setLoadedOnceUserDefaults];

    return YES;
}

//ロック&スリープ禁止の切り替え
- (void)setIdleTimer:(BOOL)isDisabled
{
    [[UIApplication sharedApplication] setIdleTimerDisabled:isDisabled];
}

//設定適用
- (void)initSettings
{
    wakeUpTime     = ![self isLoadedOnceUserDefaults] ? DEFAULT_WAKE_UP_TIME : [userDefaults stringForKey:@"UD_WAKE_UP_TIME_KEY"];
    [userDefaults setObject:wakeUpTime forKey:@"UD_WAKE_UP_TIME_KEY"];

    [userDefaults synchronize];
}

//ユーザーデフォルトの初回読み込みフラグ立てる
- (void)setLoadedOnceUserDefaults
{
    [userDefaults setBool:YES forKey:@"UD_LOADED_ONCE"];
    [userDefaults synchronize];
}

//ユーザーデフォルトが初期状態であるか
- (BOOL)isLoadedOnceUserDefaults
{
    return [userDefaults boolForKey:@"UD_LOADED_ONCE"];
}

AlarmViewController.h

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
#import <UIKit/UIKit.h>
#import "DCAudioPlayer.h"
#import "DCLabel.h"
#import "DCButton.h"
#import "DCUtil.h"

#define ALARM_NAME                   @"alarm"
#define ALARM_FILE_EXT               @"mp3"
#define ALARM_PICKER_WIDTH           320
#define ALARM_PICKER_HEIGHT          192
#define ALARM_PICKER_MINUTE_INTERVAL 5
#define ALARM_PLAY_INFINITE          -1
#define ALARM_TIME_DATE_FORMAT       @"HH:mm"
#define ALARM_TIMER_INTERVAL         1
#define ALARM_START_MESSAGE          @"アラームを開始しました。アプリを終了したりスリープさせないでください。"
#define ALARM_ERROR_MESSAGE          @"指定時刻と現在時刻が同じです"
#define ALARM_CTR_BTN_WIDTH          100
#define ALARM_CTR_BTN_HEIGHT         48
#define ALARM_CTR_BTN_Y              142
#define WAKE_UP_TIME_RECT            CGRectMake(0, 0, 320, 48)
#define WAKE_UP_TIME_LABEL_FONT      [UIFont fontWithName:@"Futura" size:16]

@interface AlarmViewController : UIViewController

@end

AlarmViewController.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#import "AlarmViewController.h"

@interface AlarmViewController ()

@property UIButton      *startAlarmButton; //アラーム停止ボタン
@property UIButton      *stopAlarmButton;  //アラーム停止ボタン
@property UILabel       *wakeUpTimeLabel;  //起床時間の表示ラベル
@property AVAudioPlayer *alarmPlayer;      //アラームプレイヤー
@property UIDatePicker  *alarmPicker;      //起床時間の選択ピッカー
@property NSTimer       *alarmTimer;       //アラームタイマー
@property BOOL          isStartedAlarm;    //アラーム開始フラグ

@end

@implementation AlarmViewController

typedef enum alarmEventType : NSUInteger {
    ALARM_START = 1,
    ALARM_STOP  = 2
} alarmEventType;

- (void)viewDidLoad
{
    [super viewDidLoad];
  
    //背景指定
    self.view.backgroundColor = [UIColor underPageBackgroundColor];

    //アラームプレイヤー初期化
    [self initAlarmPlayer];

    //起床時間の表示ビュー配置
    [self setWakeUpTimeView];

    //アラーム開始ボタン配置
    [self setAlarmControlButton:ALARM_START];

    //起床時間の選択ピッカー配置
    [self setWakeUpTimePicker];
}

#pragma mark alarm player

//アラームプレイヤー初期化
- (void)initAlarmPlayer
{
    _alarmPlayer = [[DCAudioPlayer alloc] initWithAudio:ALARM_NAME ext:ALARM_FILE_EXT isUseDelegate:NO];
}

#pragma mark wake up time label

//起床時間の表示ビュー配置
- (void)setWakeUpTimeView
{
    UIView *wakeUpTimeView = [[UIView alloc] initWithFrame:WAKE_UP_TIME_RECT];
    wakeUpTimeView.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];

    //起床時間のラベル配置
    _wakeUpTimeLabel = [DCLabel planeLabel:WAKE_UP_TIME_RECT
                                      text:wakeUpTime font:WAKE_UP_TIME_LABEL_FONT
                                 textColor:[UIColor whiteColor] textAlignment:NSTextAlignmentCenter
                           backgroundColor:[UIColor clearColor]];
    [wakeUpTimeView addSubview:_wakeUpTimeLabel];

    [self.view addSubview:wakeUpTimeView];
}

//起床時間のラベル更新
- (void)updateWakeUpTimeLabel:(NSString *)timeText
{
    _wakeUpTimeLabel.text = timeText;

    //userDefaults更新
    [userDefaults setObject:_wakeUpTimeLabel.text forKey:UD_WAKE_UP_TIME_KEY];
    [userDefaults synchronize];
}

#pragma mark alarm control button

//アラームコントロールボタン配置
- (void)setAlarmControlButton:(NSUInteger)tag
{
    //ボタン生成
    UIButton *alarmControlButton = [DCButton planeButton:CGRectMake(self.view.center.x - (ALARM_CTR_BTN_WIDTH / 2), ALARM_CTR_BTN_Y, ALARM_CTR_BTN_WIDTH, ALARM_CTR_BTN_HEIGHT)
                                                    text:_isStartedAlarm ? @"停止" : @"開始"
                                                delegate:self action:@selector(alarmControlButtonTapEvent:)
                                                     tag:_isStartedAlarm ? ALARM_STOP : ALARM_START];

    //ボタンを保持しビューに追加
    if (tag == ALARM_START) {
        _startAlarmButton = alarmControlButton;
        [self.view addSubview:_startAlarmButton];
    } else if (tag == ALARM_STOP) {
        _stopAlarmButton = alarmControlButton;
        [self.view addSubview:_stopAlarmButton];
    }
}

//アラームコントロールボタンのタップイベント
- (void)alarmControlButtonTapEvent:(UIButton *)button
{
    NSUInteger tag = button.tag;

    if (tag == ALARM_START) {
        //現在時刻と設定時刻が同じならアラートを表示し処理しない
        if ([self isCurrentTime]) {
            [DCUtil showAlert:nil message:ALARM_ERROR_MESSAGE
            cancelButtonTitle:nil otherButtonTitles:@"OK"];
            return;
        }

        //アラームタイマー開始
        [self startAlarmTimer];
    } else if (tag == ALARM_STOP) {
        //アラームタイマー停止
        [self clearAlarmTimer];

        //アラーム停止
        [self stopAlarm];
    }
    _isStartedAlarm = tag == ALARM_START;

    //アラームコントロールボタン再配置
    [self resetAlarmControlButton];
}

//アラームコントロールボタン削除
- (void)removeAlarmControlButton:(NSUInteger)tag
{
    if (tag == ALARM_START) {
        [_startAlarmButton removeFromSuperview];
    } else if (tag == ALARM_STOP) {
        [_stopAlarmButton removeFromSuperview];
    }
}

//アラームコントロールボタン再配置
- (void)resetAlarmControlButton
{
    [self removeAlarmControlButton:_isStartedAlarm ? ALARM_STOP : ALARM_START];
    [self setAlarmControlButton:_isStartedAlarm ? ALARM_STOP : ALARM_START];
}

#pragma mark alarm timer

//アラームタイマー開始
- (void)startAlarmTimer
{
    if (_isStartedAlarm) {
        return;
    }

    //スリープ禁止
    [APP_DELEGATE setIdleTimer:YES];

    //アラート表示
    [DCUtil showAlert:nil message:ALARM_START_MESSAGE
    cancelButtonTitle:nil otherButtonTitles:@"OK"];

    //タイマー停止
    [self clearAlarmTimer];

    //タイマー開始
    _alarmTimer = [NSTimer scheduledTimerWithTimeInterval:ALARM_TIMER_INTERVAL target:self
                                                 selector:@selector(alarmTimerEvent:) userInfo:nil
                                                  repeats:YES];
}

//アラームタイマーイベント
- (void)alarmTimerEvent:(NSTimer *)timer
{
    //現在時刻が設定時刻であればアラームを鳴らす
    if ([self isCurrentTime]) {
        if (_isStartedAlarm) {
            //タイマー停止
            [self clearAlarmTimer];

            //アラーム再生
            [self playAlarm];
        }
    }
}

//アラームタイマー停止
- (void)clearAlarmTimer
{
    if (!_isStartedAlarm) {
        return;
    }

    //スリープ許可
    [APP_DELEGATE setIdleTimer:NO];

    //タイマー停止
    if (_alarmTimer != NULL) {
        [_alarmTimer invalidate];
    }
}

#pragma mark play/stop alarm

//指定したアラームの再生
- (void)playAlarm
{
    [_alarmPlayer setNumberOfLoops:ALARM_PLAY_INFINITE];
    [_alarmPlayer play];
}

//指定したアラームの停止
- (void)stopAlarm
{
    if ([_alarmPlayer isPlaying]) [_alarmPlayer stop];
}

#pragma mark date picker

//起床時間の選択ピッカー配置
- (void)setWakeUpTimePicker
{
    //起床時間の選択ピッカーを入れるビュー追加
    UIView *wakeUpTimePickerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height- ALARM_PICKER_HEIGHT, ALARM_PICKER_WIDTH, ALARM_PICKER_HEIGHT)];
    [self.view addSubview:wakeUpTimePickerView];

    //起床時間の選択ピッカー初期化
    _alarmPicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, ALARM_PICKER_WIDTH, ALARM_PICKER_HEIGHT)];

    //日付の表示モードを変更する(時分を表示)
    _alarmPicker.datePickerMode = UIDatePickerModeTime;

    //何分刻みにするか
    _alarmPicker.minuteInterval = ALARM_PICKER_MINUTE_INTERVAL;

    //初期時刻設定
    [_alarmPicker setDate:[self wakeUpDate]];

    //起床時間の選択ピッカーの値が変更されたときに呼ばれるメソッドを設定
    [_alarmPicker addTarget:self
                     action:@selector(alarmPickerChanged:)
           forControlEvents:UIControlEventValueChanged];

    //UIDatePickerのインスタンスをビューに追加
    [wakeUpTimePickerView addSubview:_alarmPicker];
}

//起床時間の選択ピッカー変更時のイベント
- (void)alarmPickerChanged:(UIDatePicker *)datePicker
{
    //アラーム開始フラグを下ろす
    _isStartedAlarm = NO;

    //起床時間更新
    [self updateWakeUpTimeLabel:[self wakeUpTimeText]];

    //アラームが鳴っていたらアラーム停止
    [self stopAlarm];

    //タイマー停止
    [self clearAlarmTimer];

    //停止ボタンを開始ボタンへ変更
    [self resetAlarmControlButton];
}

#pragma mark getter method

//起床時間のテキスト取得
- (NSString *)wakeUpTimeText
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = ALARM_TIME_DATE_FORMAT;
    return [dateFormatter stringFromDate:_alarmPicker.date];
}

//起床時間取得
- (NSDate *)wakeUpDate
{
    NSString *wakeUpDateString = wakeUpTime;
    NSDateFormatter *dateFormater = [[NSDateFormatter alloc] init];
    [dateFormater setDateFormat:ALARM_TIME_DATE_FORMAT];
    NSDate *wakeUpDate = [dateFormater dateFromString:wakeUpDateString];
    return wakeUpDate;
}

//UIDatePickerで指定されている時刻(時)取得
- (NSInteger)wakeUpDatePickerHour
{
    NSDateFormatter *hourFormatter = [[NSDateFormatter alloc] init];
    [hourFormatter setLocale:[NSLocale currentLocale]];
    [hourFormatter setDateFormat:@"HH"];
    NSString *datePickerHour = [hourFormatter stringFromDate:_alarmPicker.date];
    return [datePickerHour intValue];
}

//UIDatePickerで指定されている時刻(分)取得
- (NSInteger)wakeUpDatePickerMinute
{
    NSDateFormatter *minuteFormatter = [[NSDateFormatter alloc] init];
    [minuteFormatter setLocale:[NSLocale currentLocale]];
    [minuteFormatter setDateFormat:@"mm"];
    NSString *datePickerMinute = [minuteFormatter stringFromDate:_alarmPicker.date];
    return [datePickerMinute intValue];
}

//現在時刻であるか
- (BOOL)isCurrentTime
{
    return ([self currentHour] == [self wakeUpDatePickerHour] &&
            [self currentMinute] == [self wakeUpDatePickerMinute]);
}
//現在の日付を取得
- (NSInteger)currentDay
{
    NSDateComponents *currentTimeComponents = [self currentDateComponents];
    return currentTimeComponents.day;
}

//現在の時間を取得
- (NSInteger)currentHour
{
    NSDateComponents *currentTimeComponents = [self currentDateComponents];
    return currentTimeComponents.hour;
}

//現在の分数を取得
- (NSInteger)currentMinute
{
    NSDateComponents *currentTimeComponents = [self currentDateComponents];
    return currentTimeComponents.minute;
}

//現在時刻のコンポーネント取得
- (NSDateComponents *)currentDateComponents
{
    //現在の時刻を取得
    NSDate *nowDate = [NSDate date];

    //現在時刻のコンポーネント定義
    NSDateComponents *nowComponents;
    nowComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit |
                                                              NSMinuteCalendarUnit |
                                                              NSSecondCalendarUnit)
                                                    fromDate:nowDate];
    return nowComponents;
}

@end

関連記事

お薦めの参考書

Swiftではじめる iPhoneアプリ開発の教科書 Swift 2 & Xcode 7対応
この参考書の通りに実践サンプルを作成することで、確実に力を養うことができます。サンプルコードもサイトからダウンロード出来るようになっており、特に広告の貼り方などが参考になりました。Swiftで何が出来るかを知ることができ、入門用にお薦めの1冊です。

   このエントリーをはてなブックマークに追加

About

Masaki Hirokawa (@dolice_apps)

デザインエンジニア 廣川政樹の開発ブログ。Objective-Cや Javaなど iPhone/Androidアプリ開発に関する技術情報を掲載しています。

iPhone apps

  • リラックス・ヒーリング(無料)
  • 望みが叶う!引き寄せの法則アプリ(無料)
  • ミステリー - 怖い話や不思議な体験、都市伝説まとめ
  • 浮世絵壁紙 - 美しい日本画ギャラリー(無料)
  • 綺麗な壁紙HD iPhone 7/7 Plus/SE & iPod対応(無料)
  • クールな壁紙HD iPhone 7/7 Plus/SE & iPod対応(無料)

Android apps

  • 浮世絵壁紙 - 美しい日本画ギャラリー
  • 綺麗な高画質壁紙

Objective-C Classes

Tag Cloud

ActionScript(9) ActionScript3(7) Ad(4) Adfurikun(2) AdMob(9) Android(10) Animation(17) AppDelegate(3) ARC(1) ArrayList(1) AVAudioPlayer(4) AVAudioSession(1) AVFoundation(3) Banner(2) Bitmap(1) Camera(4) CGAffineTransform(4) CGBlendMode(2) CGContextRef(1) CGImageRef(1) Classes(44) CLLocationManager(1) ConnectivityManager(1) ContentResolver(1) CoreLocation(2) Delegate(3) Device(7) Display(1) DisplayMetrics(1) Download(101) Facebook(6) Foundation(72) Framework(2) Google Analytics(1) Handler(1) iAd(6) ImageView(1) In-AppPurchase(1) iOS(12) iOS 7(15) iOS 7.1(3) iOS 8(1) iPad(7) iPhone(21) iPhone 6(4) Java(7) JavaScript(2) LINE(4) Localize(1) Magazine(1) MediaStore(1) MFComposeViewController(1) Nend(1) NetworkInfo(1) NSArray(23) NSCalendar(3) NSData(2) NSDate(7) NSDateComponents(2) NSDateFormatter(2) NSDictionary(12) NSEnumerator(1) NSIndexSet(1) NSInteger(6) NSMutableArray(17) NSMutableDictionary(5) NSMutableOrderedSet(7) NSMutableString(4) NSMutableURLRequest(1) NSNotificationCenter(1) NSNumber(1) NSObject(1) NSOrderedSet(7) NSRange(2) NSSelectorFromString(1) NSSet(6) NSString(19) NSTimer(4) NSTimeZone(1) NSURL(7) NSURLConnection(1) NSURLRequest(2) NSUserDefaults(7) NSXMLParser(2) Objective-C(222) PHP(1) Products(14) QuartzCore(3) RSS(2) Runnable(1) Sample(51) Screensaver(9) SDK(2) ShareCompat(1) Social(10) StoreKit(1) Twitter(6) UIAccelerometer(3) UIActionSheet(1) UIActivityIndicator(1) UIActivityIndicatorView(3) UIActivityViewController(1) UIAlertView(5) UIApplication(7) UIButton(4) UIColor(3) UIDatePicker(5) UIDevice(6) UIDeviceOrientation(1) UIEvent(6) UIImage(15) UIImagePickerController(4) UIImageView(12) UIKit(58) UILabel(7) UINavigationBar(4) UINavigationItem(1) UIPasteboard(4) UIScreen(1) UIScrollBar(1) UIScrollView(1) UISlider(3) UIStoryboardSegue(3) UISwitch(1) UITabBar(3) UITableView(4) UITextField(2) UIView(11) UIViewAnimationTransition(1) UIViewController(4) UIWebView(5) WindowManager(1) Xcode(48) Xcode 5(8) Xcode 5.1(2)