How to unwrap an optional into a variable and then use that variable in the next iteration of a while loop?












0















I have a method below called createNotifications() in which I try to do some fancy stuff when the recurrence of an alarm is daily. I first call self.createNotificationForToday(), which goes fine, and then start a while loop and call self.createNotificationForTomorrowAndReturnNewDateComponents() in each iteration, each time returning the new date components and using it as the input for the next iteration. This allows me to call one method each time and every time, iterate to "tomorrow" and create a notification for that day. The problem is with this part:



var newDateComponents = dateComponents
while numberOfCreatableNotifications > 0 {
guard var newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
numberOfCreatableNotifications = numberOfCreatableNotifications - 1
}


What I'm attempting to do is reinitialize the newDateComponents variable each time I go through the while loop and call the createNotificationForTomorrowAnd...() method, and use those newDateComponents as input for the next call to that method. Is there something fundamentally wrong with how I'm trying to do this? Is there a better way?





createNotifications():



private func createNotifications(dateComponents: DateComponents) {

if recurrence == .today {
createNotificationForToday(dateComponents: dateComponents)
} else if recurrence == .tomorrow {
let _ = createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: dateComponents)
} else if recurrence == .daily {
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests { (notifications) in
var numberOfCreatableNotifications = 64 - notifications.count
self.createNotificationForToday(dateComponents: dateComponents)
var newDateComponents = dateComponents
while numberOfCreatableNotifications > 0 {
guard var newDateComponents =
self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
numberOfCreatableNotifications = numberOfCreatableNotifications - 1
}
}
} else {}

}




createNotificationForToday():



private func createNotificationForToday(dateComponents: DateComponents) {

let center = UNUserNotificationCenter.current()

let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default

let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

center.add(request) { (error) in
if error != nil {
print("error (String(describing: error))")
}
}

}




createNotificationForTomorrowAndReturnNewDateComponents():



private func createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: DateComponents) -> DateComponents? {

let center = UNUserNotificationCenter.current()

let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default

let calendar = Calendar.current
guard let date = calendar.date(from: dateComponents) else {
os_log("Could not unwrap date in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: date) else {
os_log("Could not unwrap tomorrow in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)

let trigger = UNCalendarNotificationTrigger(dateMatching: newDateComponents, repeats: false)

let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

center.add(request) { (error) in
if error != nil {
print("error (String(describing: error))")
}
}

return newDateComponents

}









share|improve this question



























    0















    I have a method below called createNotifications() in which I try to do some fancy stuff when the recurrence of an alarm is daily. I first call self.createNotificationForToday(), which goes fine, and then start a while loop and call self.createNotificationForTomorrowAndReturnNewDateComponents() in each iteration, each time returning the new date components and using it as the input for the next iteration. This allows me to call one method each time and every time, iterate to "tomorrow" and create a notification for that day. The problem is with this part:



    var newDateComponents = dateComponents
    while numberOfCreatableNotifications > 0 {
    guard var newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
    os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
    return
    }
    numberOfCreatableNotifications = numberOfCreatableNotifications - 1
    }


    What I'm attempting to do is reinitialize the newDateComponents variable each time I go through the while loop and call the createNotificationForTomorrowAnd...() method, and use those newDateComponents as input for the next call to that method. Is there something fundamentally wrong with how I'm trying to do this? Is there a better way?





    createNotifications():



    private func createNotifications(dateComponents: DateComponents) {

    if recurrence == .today {
    createNotificationForToday(dateComponents: dateComponents)
    } else if recurrence == .tomorrow {
    let _ = createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: dateComponents)
    } else if recurrence == .daily {
    let center = UNUserNotificationCenter.current()
    center.getPendingNotificationRequests { (notifications) in
    var numberOfCreatableNotifications = 64 - notifications.count
    self.createNotificationForToday(dateComponents: dateComponents)
    var newDateComponents = dateComponents
    while numberOfCreatableNotifications > 0 {
    guard var newDateComponents =
    self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
    os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
    return
    }
    numberOfCreatableNotifications = numberOfCreatableNotifications - 1
    }
    }
    } else {}

    }




    createNotificationForToday():



    private func createNotificationForToday(dateComponents: DateComponents) {

    let center = UNUserNotificationCenter.current()

    let content = UNMutableNotificationContent()
    content.title = "Random Alarm"
    content.subtitle = "It's time!"
    content.body = self.note
    content.sound = UNNotificationSound.default

    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

    let uuidString = UUID().uuidString
    let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

    center.add(request) { (error) in
    if error != nil {
    print("error (String(describing: error))")
    }
    }

    }




    createNotificationForTomorrowAndReturnNewDateComponents():



    private func createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: DateComponents) -> DateComponents? {

    let center = UNUserNotificationCenter.current()

    let content = UNMutableNotificationContent()
    content.title = "Random Alarm"
    content.subtitle = "It's time!"
    content.body = self.note
    content.sound = UNNotificationSound.default

    let calendar = Calendar.current
    guard let date = calendar.date(from: dateComponents) else {
    os_log("Could not unwrap date in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
    return nil
    }
    guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: date) else {
    os_log("Could not unwrap tomorrow in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
    return nil
    }
    let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)

    let trigger = UNCalendarNotificationTrigger(dateMatching: newDateComponents, repeats: false)

    let uuidString = UUID().uuidString
    let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

    center.add(request) { (error) in
    if error != nil {
    print("error (String(describing: error))")
    }
    }

    return newDateComponents

    }









    share|improve this question

























      0












      0








      0








      I have a method below called createNotifications() in which I try to do some fancy stuff when the recurrence of an alarm is daily. I first call self.createNotificationForToday(), which goes fine, and then start a while loop and call self.createNotificationForTomorrowAndReturnNewDateComponents() in each iteration, each time returning the new date components and using it as the input for the next iteration. This allows me to call one method each time and every time, iterate to "tomorrow" and create a notification for that day. The problem is with this part:



      var newDateComponents = dateComponents
      while numberOfCreatableNotifications > 0 {
      guard var newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
      os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
      return
      }
      numberOfCreatableNotifications = numberOfCreatableNotifications - 1
      }


      What I'm attempting to do is reinitialize the newDateComponents variable each time I go through the while loop and call the createNotificationForTomorrowAnd...() method, and use those newDateComponents as input for the next call to that method. Is there something fundamentally wrong with how I'm trying to do this? Is there a better way?





      createNotifications():



      private func createNotifications(dateComponents: DateComponents) {

      if recurrence == .today {
      createNotificationForToday(dateComponents: dateComponents)
      } else if recurrence == .tomorrow {
      let _ = createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: dateComponents)
      } else if recurrence == .daily {
      let center = UNUserNotificationCenter.current()
      center.getPendingNotificationRequests { (notifications) in
      var numberOfCreatableNotifications = 64 - notifications.count
      self.createNotificationForToday(dateComponents: dateComponents)
      var newDateComponents = dateComponents
      while numberOfCreatableNotifications > 0 {
      guard var newDateComponents =
      self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
      os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
      return
      }
      numberOfCreatableNotifications = numberOfCreatableNotifications - 1
      }
      }
      } else {}

      }




      createNotificationForToday():



      private func createNotificationForToday(dateComponents: DateComponents) {

      let center = UNUserNotificationCenter.current()

      let content = UNMutableNotificationContent()
      content.title = "Random Alarm"
      content.subtitle = "It's time!"
      content.body = self.note
      content.sound = UNNotificationSound.default

      let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

      let uuidString = UUID().uuidString
      let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

      center.add(request) { (error) in
      if error != nil {
      print("error (String(describing: error))")
      }
      }

      }




      createNotificationForTomorrowAndReturnNewDateComponents():



      private func createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: DateComponents) -> DateComponents? {

      let center = UNUserNotificationCenter.current()

      let content = UNMutableNotificationContent()
      content.title = "Random Alarm"
      content.subtitle = "It's time!"
      content.body = self.note
      content.sound = UNNotificationSound.default

      let calendar = Calendar.current
      guard let date = calendar.date(from: dateComponents) else {
      os_log("Could not unwrap date in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
      return nil
      }
      guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: date) else {
      os_log("Could not unwrap tomorrow in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
      return nil
      }
      let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)

      let trigger = UNCalendarNotificationTrigger(dateMatching: newDateComponents, repeats: false)

      let uuidString = UUID().uuidString
      let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

      center.add(request) { (error) in
      if error != nil {
      print("error (String(describing: error))")
      }
      }

      return newDateComponents

      }









      share|improve this question














      I have a method below called createNotifications() in which I try to do some fancy stuff when the recurrence of an alarm is daily. I first call self.createNotificationForToday(), which goes fine, and then start a while loop and call self.createNotificationForTomorrowAndReturnNewDateComponents() in each iteration, each time returning the new date components and using it as the input for the next iteration. This allows me to call one method each time and every time, iterate to "tomorrow" and create a notification for that day. The problem is with this part:



      var newDateComponents = dateComponents
      while numberOfCreatableNotifications > 0 {
      guard var newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
      os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
      return
      }
      numberOfCreatableNotifications = numberOfCreatableNotifications - 1
      }


      What I'm attempting to do is reinitialize the newDateComponents variable each time I go through the while loop and call the createNotificationForTomorrowAnd...() method, and use those newDateComponents as input for the next call to that method. Is there something fundamentally wrong with how I'm trying to do this? Is there a better way?





      createNotifications():



      private func createNotifications(dateComponents: DateComponents) {

      if recurrence == .today {
      createNotificationForToday(dateComponents: dateComponents)
      } else if recurrence == .tomorrow {
      let _ = createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: dateComponents)
      } else if recurrence == .daily {
      let center = UNUserNotificationCenter.current()
      center.getPendingNotificationRequests { (notifications) in
      var numberOfCreatableNotifications = 64 - notifications.count
      self.createNotificationForToday(dateComponents: dateComponents)
      var newDateComponents = dateComponents
      while numberOfCreatableNotifications > 0 {
      guard var newDateComponents =
      self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
      os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
      return
      }
      numberOfCreatableNotifications = numberOfCreatableNotifications - 1
      }
      }
      } else {}

      }




      createNotificationForToday():



      private func createNotificationForToday(dateComponents: DateComponents) {

      let center = UNUserNotificationCenter.current()

      let content = UNMutableNotificationContent()
      content.title = "Random Alarm"
      content.subtitle = "It's time!"
      content.body = self.note
      content.sound = UNNotificationSound.default

      let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

      let uuidString = UUID().uuidString
      let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

      center.add(request) { (error) in
      if error != nil {
      print("error (String(describing: error))")
      }
      }

      }




      createNotificationForTomorrowAndReturnNewDateComponents():



      private func createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: DateComponents) -> DateComponents? {

      let center = UNUserNotificationCenter.current()

      let content = UNMutableNotificationContent()
      content.title = "Random Alarm"
      content.subtitle = "It's time!"
      content.body = self.note
      content.sound = UNNotificationSound.default

      let calendar = Calendar.current
      guard let date = calendar.date(from: dateComponents) else {
      os_log("Could not unwrap date in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
      return nil
      }
      guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: date) else {
      os_log("Could not unwrap tomorrow in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
      return nil
      }
      let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)

      let trigger = UNCalendarNotificationTrigger(dateMatching: newDateComponents, repeats: false)

      let uuidString = UUID().uuidString
      let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

      center.add(request) { (error) in
      if error != nil {
      print("error (String(describing: error))")
      }
      }

      return newDateComponents

      }






      ios swift






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 26 '18 at 6:15









      Tyler CheekTyler Cheek

      639




      639
























          2 Answers
          2






          active

          oldest

          votes


















          1














          The scope of a variable created by a guard statement is the block that contains the guard statement, which is the body of your while loop.



          This means that the newDateComponents you are creating with your guard statement is not the same as the newDateComponents you created outside the while and the inner newDateComponents will be discarded after each iteration of the while loop.



          You don't actually need the guard statement; you can build the unwrap into your while:



          var newDateComponents: DateComponents? = dateComponents
          while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
          newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
          numberOfCreatableNotifications -= 1
          }
          if numberOfCreateableNotifications > 0 {
          os_log("Could not create all notifications
          }


          You can probably refactor this to be a bit more efficient and have one less function:




          • Use a Calendar property so that you don't need to keep instantiating the calendar

          • Have a function to return "tomorrow"

          • Have a function to schedule a notification




          let calendar = Calendar.autoUpdatingCurrent

          private func createNotifications(dateComponents: DateComponents) {

          switch (recurrence) {
          case .today:
          createNotification(for: dateComponents)
          case .tomorrow:
          createNotification(for: day(after: dateComponents))
          case .daily:
          let center = UNUserNotificationCenter.current()
          center.getPendingNotificationRequests { (notifications) in
          var numberOfCreatableNotifications = 64 - notifications.count
          var currentDay: DateComponents? = dateComponents
          while numberOfCreatableNotifications > 0, current = currentDay {
          createNotification(for: current)
          currentDay = day(after: current)
          numberOfCreateableNotification -= 1
          }
          if numberOfCreateableNotifications > 0 {
          os_log("Could not create all notifications", type: .debug)
          }
          }
          }
          }


          private func createNotification(for dateComponents: DateComponents) {

          let center = UNUserNotificationCenter.current()

          let content = UNMutableNotificationContent()
          content.title = "Random Alarm"
          content.subtitle = "It's time!"
          content.body = self.note
          content.sound = UNNotificationSound.default

          let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

          let uuidString = UUID().uuidString
          let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

          center.add(request) { (error) in
          if let err = error {
          print("error (err.localizedDescription)")
          }
          }
          }



          private func day(after dateComponents: DateComponents) -> DateComponents? {

          guard let date = calendar.date(from: dateComponents),
          let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
          else {
          os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
          return nil
          }
          let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
          return newDateComponents

          }


          One final note, it would probably be nicer to pass Date instances rather than DateComponent instances and convert to DateComponent once when you need to actually schedule the notification.






          share|improve this answer


























          • Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

            – Tyler Cheek
            Nov 27 '18 at 1:52





















          1














          You cannot directly bind to the variable newDateComponents from the
          outer scope in the guard-statement. You can bind to a new variable and
          then assign that to newDateComponents:



          var newDateComponents = dateComponents
          while numberOfCreatableNotifications > 0 {
          guard let nextDateComponents =
          self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
          os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
          return
          }
          newDateComponents = nextDateComponents
          numberOfCreatableNotifications = numberOfCreatableNotifications - 1
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53475632%2fhow-to-unwrap-an-optional-into-a-variable-and-then-use-that-variable-in-the-next%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            The scope of a variable created by a guard statement is the block that contains the guard statement, which is the body of your while loop.



            This means that the newDateComponents you are creating with your guard statement is not the same as the newDateComponents you created outside the while and the inner newDateComponents will be discarded after each iteration of the while loop.



            You don't actually need the guard statement; you can build the unwrap into your while:



            var newDateComponents: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
            newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
            numberOfCreatableNotifications -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications
            }


            You can probably refactor this to be a bit more efficient and have one less function:




            • Use a Calendar property so that you don't need to keep instantiating the calendar

            • Have a function to return "tomorrow"

            • Have a function to schedule a notification




            let calendar = Calendar.autoUpdatingCurrent

            private func createNotifications(dateComponents: DateComponents) {

            switch (recurrence) {
            case .today:
            createNotification(for: dateComponents)
            case .tomorrow:
            createNotification(for: day(after: dateComponents))
            case .daily:
            let center = UNUserNotificationCenter.current()
            center.getPendingNotificationRequests { (notifications) in
            var numberOfCreatableNotifications = 64 - notifications.count
            var currentDay: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, current = currentDay {
            createNotification(for: current)
            currentDay = day(after: current)
            numberOfCreateableNotification -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications", type: .debug)
            }
            }
            }
            }


            private func createNotification(for dateComponents: DateComponents) {

            let center = UNUserNotificationCenter.current()

            let content = UNMutableNotificationContent()
            content.title = "Random Alarm"
            content.subtitle = "It's time!"
            content.body = self.note
            content.sound = UNNotificationSound.default

            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

            let uuidString = UUID().uuidString
            let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

            center.add(request) { (error) in
            if let err = error {
            print("error (err.localizedDescription)")
            }
            }
            }



            private func day(after dateComponents: DateComponents) -> DateComponents? {

            guard let date = calendar.date(from: dateComponents),
            let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
            else {
            os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
            return nil
            }
            let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
            return newDateComponents

            }


            One final note, it would probably be nicer to pass Date instances rather than DateComponent instances and convert to DateComponent once when you need to actually schedule the notification.






            share|improve this answer


























            • Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

              – Tyler Cheek
              Nov 27 '18 at 1:52


















            1














            The scope of a variable created by a guard statement is the block that contains the guard statement, which is the body of your while loop.



            This means that the newDateComponents you are creating with your guard statement is not the same as the newDateComponents you created outside the while and the inner newDateComponents will be discarded after each iteration of the while loop.



            You don't actually need the guard statement; you can build the unwrap into your while:



            var newDateComponents: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
            newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
            numberOfCreatableNotifications -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications
            }


            You can probably refactor this to be a bit more efficient and have one less function:




            • Use a Calendar property so that you don't need to keep instantiating the calendar

            • Have a function to return "tomorrow"

            • Have a function to schedule a notification




            let calendar = Calendar.autoUpdatingCurrent

            private func createNotifications(dateComponents: DateComponents) {

            switch (recurrence) {
            case .today:
            createNotification(for: dateComponents)
            case .tomorrow:
            createNotification(for: day(after: dateComponents))
            case .daily:
            let center = UNUserNotificationCenter.current()
            center.getPendingNotificationRequests { (notifications) in
            var numberOfCreatableNotifications = 64 - notifications.count
            var currentDay: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, current = currentDay {
            createNotification(for: current)
            currentDay = day(after: current)
            numberOfCreateableNotification -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications", type: .debug)
            }
            }
            }
            }


            private func createNotification(for dateComponents: DateComponents) {

            let center = UNUserNotificationCenter.current()

            let content = UNMutableNotificationContent()
            content.title = "Random Alarm"
            content.subtitle = "It's time!"
            content.body = self.note
            content.sound = UNNotificationSound.default

            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

            let uuidString = UUID().uuidString
            let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

            center.add(request) { (error) in
            if let err = error {
            print("error (err.localizedDescription)")
            }
            }
            }



            private func day(after dateComponents: DateComponents) -> DateComponents? {

            guard let date = calendar.date(from: dateComponents),
            let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
            else {
            os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
            return nil
            }
            let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
            return newDateComponents

            }


            One final note, it would probably be nicer to pass Date instances rather than DateComponent instances and convert to DateComponent once when you need to actually schedule the notification.






            share|improve this answer


























            • Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

              – Tyler Cheek
              Nov 27 '18 at 1:52
















            1












            1








            1







            The scope of a variable created by a guard statement is the block that contains the guard statement, which is the body of your while loop.



            This means that the newDateComponents you are creating with your guard statement is not the same as the newDateComponents you created outside the while and the inner newDateComponents will be discarded after each iteration of the while loop.



            You don't actually need the guard statement; you can build the unwrap into your while:



            var newDateComponents: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
            newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
            numberOfCreatableNotifications -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications
            }


            You can probably refactor this to be a bit more efficient and have one less function:




            • Use a Calendar property so that you don't need to keep instantiating the calendar

            • Have a function to return "tomorrow"

            • Have a function to schedule a notification




            let calendar = Calendar.autoUpdatingCurrent

            private func createNotifications(dateComponents: DateComponents) {

            switch (recurrence) {
            case .today:
            createNotification(for: dateComponents)
            case .tomorrow:
            createNotification(for: day(after: dateComponents))
            case .daily:
            let center = UNUserNotificationCenter.current()
            center.getPendingNotificationRequests { (notifications) in
            var numberOfCreatableNotifications = 64 - notifications.count
            var currentDay: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, current = currentDay {
            createNotification(for: current)
            currentDay = day(after: current)
            numberOfCreateableNotification -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications", type: .debug)
            }
            }
            }
            }


            private func createNotification(for dateComponents: DateComponents) {

            let center = UNUserNotificationCenter.current()

            let content = UNMutableNotificationContent()
            content.title = "Random Alarm"
            content.subtitle = "It's time!"
            content.body = self.note
            content.sound = UNNotificationSound.default

            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

            let uuidString = UUID().uuidString
            let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

            center.add(request) { (error) in
            if let err = error {
            print("error (err.localizedDescription)")
            }
            }
            }



            private func day(after dateComponents: DateComponents) -> DateComponents? {

            guard let date = calendar.date(from: dateComponents),
            let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
            else {
            os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
            return nil
            }
            let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
            return newDateComponents

            }


            One final note, it would probably be nicer to pass Date instances rather than DateComponent instances and convert to DateComponent once when you need to actually schedule the notification.






            share|improve this answer















            The scope of a variable created by a guard statement is the block that contains the guard statement, which is the body of your while loop.



            This means that the newDateComponents you are creating with your guard statement is not the same as the newDateComponents you created outside the while and the inner newDateComponents will be discarded after each iteration of the while loop.



            You don't actually need the guard statement; you can build the unwrap into your while:



            var newDateComponents: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
            newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
            numberOfCreatableNotifications -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications
            }


            You can probably refactor this to be a bit more efficient and have one less function:




            • Use a Calendar property so that you don't need to keep instantiating the calendar

            • Have a function to return "tomorrow"

            • Have a function to schedule a notification




            let calendar = Calendar.autoUpdatingCurrent

            private func createNotifications(dateComponents: DateComponents) {

            switch (recurrence) {
            case .today:
            createNotification(for: dateComponents)
            case .tomorrow:
            createNotification(for: day(after: dateComponents))
            case .daily:
            let center = UNUserNotificationCenter.current()
            center.getPendingNotificationRequests { (notifications) in
            var numberOfCreatableNotifications = 64 - notifications.count
            var currentDay: DateComponents? = dateComponents
            while numberOfCreatableNotifications > 0, current = currentDay {
            createNotification(for: current)
            currentDay = day(after: current)
            numberOfCreateableNotification -= 1
            }
            if numberOfCreateableNotifications > 0 {
            os_log("Could not create all notifications", type: .debug)
            }
            }
            }
            }


            private func createNotification(for dateComponents: DateComponents) {

            let center = UNUserNotificationCenter.current()

            let content = UNMutableNotificationContent()
            content.title = "Random Alarm"
            content.subtitle = "It's time!"
            content.body = self.note
            content.sound = UNNotificationSound.default

            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

            let uuidString = UUID().uuidString
            let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)

            center.add(request) { (error) in
            if let err = error {
            print("error (err.localizedDescription)")
            }
            }
            }



            private func day(after dateComponents: DateComponents) -> DateComponents? {

            guard let date = calendar.date(from: dateComponents),
            let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
            else {
            os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
            return nil
            }
            let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
            return newDateComponents

            }


            One final note, it would probably be nicer to pass Date instances rather than DateComponent instances and convert to DateComponent once when you need to actually schedule the notification.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 26 '18 at 6:56

























            answered Nov 26 '18 at 6:38









            Paulw11Paulw11

            70.2k1088104




            70.2k1088104













            • Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

              – Tyler Cheek
              Nov 27 '18 at 1:52





















            • Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

              – Tyler Cheek
              Nov 27 '18 at 1:52



















            Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

            – Tyler Cheek
            Nov 27 '18 at 1:52







            Thanks! This is exactly what I needed to see. The only problems: 1. Getting Value of optional type 'DateComponents?' must be unwrapped to a value of type 'DateComponents' error on line createNotification(for: day(after: dateComponents)). How best to fix that? 2. current isn't defined anywhere. Can I just initialize that anywhere above the while loop? 3. while numberOfCreatableNotifications > 0, current = currentDay doesn't seem to be playing nicely with the compiler. Should it be current == currentDay? 4. How do I unwrap current for createNotification(for: current)

            – Tyler Cheek
            Nov 27 '18 at 1:52















            1














            You cannot directly bind to the variable newDateComponents from the
            outer scope in the guard-statement. You can bind to a new variable and
            then assign that to newDateComponents:



            var newDateComponents = dateComponents
            while numberOfCreatableNotifications > 0 {
            guard let nextDateComponents =
            self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
            os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
            return
            }
            newDateComponents = nextDateComponents
            numberOfCreatableNotifications = numberOfCreatableNotifications - 1
            }





            share|improve this answer




























              1














              You cannot directly bind to the variable newDateComponents from the
              outer scope in the guard-statement. You can bind to a new variable and
              then assign that to newDateComponents:



              var newDateComponents = dateComponents
              while numberOfCreatableNotifications > 0 {
              guard let nextDateComponents =
              self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
              os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
              return
              }
              newDateComponents = nextDateComponents
              numberOfCreatableNotifications = numberOfCreatableNotifications - 1
              }





              share|improve this answer


























                1












                1








                1







                You cannot directly bind to the variable newDateComponents from the
                outer scope in the guard-statement. You can bind to a new variable and
                then assign that to newDateComponents:



                var newDateComponents = dateComponents
                while numberOfCreatableNotifications > 0 {
                guard let nextDateComponents =
                self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
                os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
                return
                }
                newDateComponents = nextDateComponents
                numberOfCreatableNotifications = numberOfCreatableNotifications - 1
                }





                share|improve this answer













                You cannot directly bind to the variable newDateComponents from the
                outer scope in the guard-statement. You can bind to a new variable and
                then assign that to newDateComponents:



                var newDateComponents = dateComponents
                while numberOfCreatableNotifications > 0 {
                guard let nextDateComponents =
                self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
                os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
                return
                }
                newDateComponents = nextDateComponents
                numberOfCreatableNotifications = numberOfCreatableNotifications - 1
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 26 '18 at 6:32









                Martin RMartin R

                403k56894994




                403k56894994






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53475632%2fhow-to-unwrap-an-optional-into-a-variable-and-then-use-that-variable-in-the-next%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Wiesbaden

                    Marschland

                    Dieringhausen