Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue-iOS] If iCloud is on, then the calendar doesn't show up :( #10

Closed
jamesmontemagno opened this issue Feb 10, 2016 · 25 comments
Closed

Comments

@jamesmontemagno
Copy link
Contributor

I am working on this via:
http://stackoverflow.com/questions/15706969/how-to-create-and-save-ekcalendar-on-ios-6

It is a bummer. I am thinking that having a method called "GetDefaultCalendarAsync" would be nice to have as sometimes that is what you want to do.

I am going to implement how they have it on stackoverflow. I have read several articles now saying the same thing.

@jamesmontemagno
Copy link
Contributor Author

Fixed with: #9

Now using default calendar. Verified and ran all tests and working great on devices.

@TheAlmightyBob
Copy link
Owner

Wow, that's an annoying one! And I have indeed reproduced it myself now. Thanks for tracking this down!

My only concern is that point Steven Wei raises in the SO comments, that matching on the "iCloud" name might not be reliable. Apple did remove the ability to rename the account as of iOS8, but that wouldn't affect phones that were upgraded from previous versions and already had renamed accounts. Also, when looking this up, I found discussion threads where users were sharing tricks for how to get around this and still rename their accounts. :-P

But you say you found several articles supporting this technique? Suggesting that there's really just no better way? If it's all we can do, it's better than nothing, but man...

@jamesmontemagno
Copy link
Contributor Author

Yeah, it is a sad sad reality that they simply do not want you doing that. However, I think this approach works great because you will 99% of the time get a valid default calendar and that default calendar source is the iCloud source. Which is the best way to get it from my readings.

@TheAlmightyBob
Copy link
Owner

So, on my personal device, my default calendar is Gmail, not iCloud.

Do you expect this will still work? Do we assume that, since the Gmail calendar does show up, that its source would still be what you want? Is that going to cause your created calendar to be sorted into the Gmail category?

@jamesmontemagno
Copy link
Contributor Author

Hmmmm I will have to configure that in my phone and test it out. Curious
what it will do, I assume it would add the source as Google, which may be
wrong. Maybe I should only check for the icloud.

On your device does it still show local calendars and can you create them
locally still?
On Feb 10, 2016 10:05 PM, "Caleb Clarke" notifications@github.com wrote:

So, on my personal device, my default calendar is Gmail, not iCloud.

Do you expect this will still work? Do we assume that, since the Gmail
calendar does show up, that its source would still be what you want? Is
that going to cause your created calendar to be sorted into the Gmail
category?


Reply to this email directly or view it on GitHub
#10 (comment)
.

@TheAlmightyBob
Copy link
Owner

No. With Gmail as the default calendar, but also having non-default iCloud calendars, I still reproduce the issue.

[I'm really surprised I didn't notice this before... could've sworn I did at least some on-device testing for iOS...]

@jamesmontemagno
Copy link
Contributor Author

So I looked at a phone with gmail setup and it looks like if it is the only one setup you can't create local calendars and they wont show up. iOS is very strange to be honest and I don't understand.

With your phone were you able to create a calendar on the gmail account? I assume it is the default Source and would work alright?

@jamesmontemagno
Copy link
Contributor Author

Android is also very tricky as users can't really delete calendars in the default google calendar app at all, which is strange. My thought really is to create a new method to return the "default" calendar to insert events on. In this instance on android it is just the first writable calendar, on iOS it is the defaultcalendarfornewevents, and windows... gotta look into, but probably the same as Android

@jamesmontemagno
Copy link
Contributor Author

http://oleb.net/blog/2012/05/creating-and-deleting-calendars-in-ios/ is where I was reading.

Interesting though... I wonder if I just create a calendar on iOS and if I set reminders I guess they would still do a pop up for the event. The user just can't get to them to see details. Calendars are hard.

@TheAlmightyBob
Copy link
Owner

I'm not sure about the gmail thing. Gmail is my default, but I also have iCloud, and I've only tested with the original code, not your change.

This sounds pretty nuts. There are a bunch of 3rd-party calendar apps... I wonder how they handle it.

I can speak more to the Android/WinPhone thing:
The default Google calendar app does limit deletion of calendars for some reason, but that is a quirk of that app. Other apps, such as the Samsung calendar, allow it. I don't think the Google app allows creating calendars either?
So I realize that's not ideal, but I'm not sure what to do about it, other than what you suggested or providing an option in your app to remove its calendar.

There already exist third-party apps that are affected by this. For example, MobiMail, which will synchronize an Exchange (or O365) calendar into a custom local device calendar that it creates. Can't delete that from Google Calendar app either.

Windows is not like Android. Unless this has been changed in a recent update, Windows will not allow you to write to the default calendar. You must create a calendar for your app.

"Calendars are hard"++

@jamesmontemagno
Copy link
Contributor Author

Interesting, so in your original and current master branch code if you
create a calendar and have both icloud and Google calendar enabled what
happens? Does the local store show up? I will test this today when I get
off my flight to see if I can figure out a good flow.

My thought is maybe to pull icloud first, else just get local as the
source, however if you only have Google setup I am not sure what will
happen. Will test.

These are valid points about Android and the calendar you create does show
up in the default app so that is good. Developers just get to decide what
they want to do.

So, for the default calendar method I think that iOS could return the
default, Android returns first writable, and Windows then would be first
writable. And I could document that it can return null, which means there
is no default calendar and you need to create one. This might be acceptable
for anyone that just wants to create events on a calendar.
On Feb 11, 2016 9:29 AM, "Caleb Clarke" notifications@github.com wrote:

I'm not sure about the gmail thing. Gmail is my default, but I also have
iCloud, and I've only tested with the original code, not your change.

This sounds pretty nuts. There are a bunch of 3rd-party calendar apps... I
wonder how they handle it.

I can speak more to the Android/WinPhone thing:
The default Google calendar app does limit deletion of calendars for some
reason, but that is a quirk of that app. Other apps, such as the Samsung
calendar, allow it. I don't think the Google app allows creating calendars
either?
So I realize that's not ideal, but I'm not sure what to do about it, other
than what you suggested or providing an option in your app to remove its
calendar.

There already exist third-party apps that are affected by this. For
example, MobiMail, which will synchronize an Exchange (or O365) calendar
into a custom local device calendar that it creates. Can't delete that from
Google Calendar app either.

Windows is not like Android. Unless this has been changed in a recent
update, Windows will not allow you to write to the default calendar. You
must create a calendar for your app.

"Calendars are hard"++


Reply to this email directly or view it on GitHub
#10 (comment)
.

@TheAlmightyBob
Copy link
Owner

It does not show up. That's why I said above I'm so surprised I missed this issue. I'm sure I was testing on devices as well as simulator (except on WinPhone, as I don't have one), but I have no evidence now to prove that belief...

The default calendar method isn't a bad idea. I hate for it to be necessary though... and personally as a user I would generally prefer that apps keep their own calendars rather than cluttering my personal calendar (so it gets different colors, can be hidden/shown, etc). I'm really really curious how other apps deal with this.

From an app perspective, you can also let the user choose rather than just automatically using the default. That's what my TripSketch app does... provide a list of writable calendars for export, with an optional "New Calendar" button. Certainly it's not perfect and involves extra steps/taps, but thought I'd mention it.

@jamesmontemagno
Copy link
Contributor Author

Yeah, that is a good point. I think probably best practice is to pick a
calendar that is editable, else create a new one. Maybe I will go this
path....

The only question that remains for us is what happens when we create a
calendar on iOS and what source should it be.

There are really three scenarios and what is in Master branch:

1.) WORKS AS IS TODAY: App that just wants to add an event to a calendar.
In this case then just do what you said and show a list of valid calendars.

2.) WORKS AS IS TODAY: App that wants to create its own local calendar and
doesn't care if it shows up in other apps.

3.) IN PROGRESS: App that wants to create their own calendar and should be
visible in other Calendar apps. This works fine on Android (with my sync
fix) & Windows, however we run into an issue on iOS. On iOS this only works
if they have a local calendar. With my first fix it will add it to at least
iCloud, which is good... unless they turn off iCloud lol, but not sure
about other defaults that have to be tested.

Any user stories I am missing?

On Thu, Feb 11, 2016 at 11:43 AM, Caleb Clarke notifications@github.com
wrote:

It does not show up. That's why I said above I'm so surprised I missed
this issue. I'm sure I was testing on devices as well as simulator (except
on WinPhone, as I don't have one), but I have no evidence now to prove that
belief...

The default calendar method isn't a bad idea. I hate for it to be
necessary though... and personally as a user I would generally prefer that
apps keep their own calendars rather than cluttering my personal calendar
(so it gets different colors, can be hidden/shown, etc). I'm really really
curious how other apps deal with this.

From an app perspective, you can also let the user choose rather than just
automatically using the default. That's what my TripSketch app does...
provide a list of writable calendars for export, with an optional "New
Calendar" button. Certainly it's not perfect and involves extra steps/taps,
but thought I'd mention it.


Reply to this email directly or view it on GitHub
#10 (comment)
.

James Montemagno
http://www.montemagno.com
@jamesmontemagno http://www.twitter.com/jamesmontemagno

@jamesmontemagno
Copy link
Contributor Author

So just ran some tests today:

1.) Works
2.) Works
3.) Here is the break down:

3.1) Only local calendar is on phone -> Returns local calendar source
3.2) Only iCloud is on -> Returns caldev - iCloud source
3.2) iCloud and Google calendar are on -> returns caldev - iCloud source
3.3) Only Google calendar is on -> Returns the google calendar source, but throws an exception as you can not insert calendars into that one.

So I am making some modifications to
1.) Check if default calenders source is iCloud and if so then use that, else use local.

I think you are correct that the best thing to do is ask the user what calendar that is modifiable that they want to insert it into.

@jamesmontemagno
Copy link
Contributor Author

Let me now what you think of the latest changes

@TheAlmightyBob
Copy link
Owner

Are you sure that scenario 2 works? I was under the impression that the created local calendar was not returned via the api if iCloud was enabled? Or is it actually still available by ID, but just invisible when enumerating calendars?

In your test results, when you say "returns," what is returning that? I assume you mean your previous logic to select a source?

Re: your proposed modification, don't you want to use iCloud as long as it's available, regardless of whether it's default? i.e. wasn't 3.2 the behavior you wanted?

Because the problem with 3.3 isn't that Google is the default, it's that Google is the only one, right? That's when neither local nor iCloud worked?

I'm kinda leaning towards just throwing an exception in the case where we don't think we can successfully create a calendar that will be visible, rather than just falling back to creating an invisible one (this is assuming that these calendars are actually being created successfully and just not showing up). While I can dream up use cases for an invisible calendar, I can more easily think of problems... e.g. user deletes your app, calendar is stuck on their device forever now.

@jamesmontemagno
Copy link
Contributor Author

So, if icloud is enabled, you can still create a calendar on local as it is
returned, but will be hidden. You could then disable icloud and see the
calendar that was created.

I think from reading that only icloud and local are writable with new
calendars. If you turn on and off icloud it can still show up in the list
of sources.

So the idea is basically this...

Is your current calendar icloud? If yes then use it. If it isn't then put
it on local calendar.

Now... What you could do is say... Is the current calendar either icloud or
local then use it. Else throw exception. That may be the way to do it.

Thoughts?
On Feb 11, 2016 7:37 PM, "Caleb Clarke" notifications@github.com wrote:

Are you sure that scenario 2 works? I was under the impression that the
created local calendar was not returned via the api if iCloud was enabled?
Or is it actually still available by ID, but just invisible when
enumerating calendars?

In your test results, when you say "returns," what is returning that? I
assume you mean your previous logic to select a source?

Re: your proposed modification, don't you want to use iCloud as long as
it's available, regardless of whether it's default? i.e. wasn't 3.2 the
behavior you wanted?

Because the problem with 3.3 isn't that Google is the default, it's that
Google is the only one, right? That's when neither local nor iCloud
worked?

I'm kinda leaning towards just throwing an exception in the case where we
don't think we can successfully create a calendar that will be visible,
rather than just falling back to creating an invisible one (this is
assuming that these calendars are actually being created successfully and
just not showing up). While I can dream up use cases for an invisible
calendar, I can more easily think of problems... e.g. user deletes your
app, calendar is stuck on their device forever now.


Reply to this email directly or view it on GitHub
#10 (comment)
.

@TheAlmightyBob
Copy link
Owner

So you're saying that if I've enabled the iCloud calendars, then disabled them, iCloud will still be returned by eventStore.Sources, and then of course if we use that it won't show up? Have you checked if EKEventSource.calendarsForEntityType returns anything in that scenario? Maybe that could be used to determine if iCloud is enabled? Or enumerating the calendars and checking their sources?

Because it seems like what you really want is "is iCloud enabled, regardless of whether it is the default? If so, use it." I haven't yet seen anything that convinces me of the special significance of the default calendar's source. It seems like a fragile shortcut...? Unless there's literally no reliable way to determine whether iCloud is enabled and the best we can do is make a guess on default...

I'm most concerned by your earlier described scenario: "So I looked at a phone with gmail setup and it looks like if it is the only one setup you can't create local calendars and they wont show up." It seemed like, if you had local/iCloud/Gmail enabled (thus local is hidden) and disabled iCloud, local calendars would appear regardless of Gmail? Or am I mistaken and you need to disable both? So was the problem specifically that if the user never created any local calendars, and iCloud wasn't enabled but Gmail was, then you couldn't add new local calendars and have them show up? Was it that the event store simply wasn't returning "local" as an available source?

I did some quick experimenting myself (not coding). Some observations:

  • When enabling iCloud calendars, iOS actually prompts about migrating local calendars to iCloud, indicating that it is indeed intended to be an either/or situation.
  • You are indeed right that the local calendars do get created and are just hidden, then revealed upon disabling iCloud.
  • I grabbed a whole bunch of calendar replacement apps. To my surprise, not a single one allowed creating calendars! (very different from Android, where most support this)
  • I did find one app that supported exporting to its own calendar (another trip planning app). It seemed to also be affected by this issue... when I disabled iCloud, suddenly a local calendar appeared for it.

@jamesmontemagno
Copy link
Contributor Author

Hey there!

So in my testing, the "Local" source was always available and you could always create calendars on it.

If iCloud is enabled at all then it because the default calendar and data source (I assume that is how Apple wants it).

If iCloud and Google are there then both show up. iCloud is default calendar and data source. You can still write to Local calendar data source.

Hmmmm... So the question really is this:
1.) Turn off iCloud all together and does it show up in the available data sources that we can write to?
2.) If we turn it on, but don't turn on calendars does it show up?
3.) Turn on calendars and it should show up.

So, most likely if people have iCloud turned on then Calendars will be on too. So to go back to the best solution....

If iCloud is in sources use it. If not then use local.

I can change this code around today.

@TheAlmightyBob
Copy link
Owner

"If iCloud is enabled at all then it because the default calendar " -- you're sure?? So defaultCalendarForNewEvents is unrelated to the user-editable default calendar selection in Settings?? That seems very strange...

This StackOverflow answer is roughly what I had in mind: http://stackoverflow.com/a/22157141

He also adds the additional step of "if we don't find any sources named iCloud, but we do find CalDAV sources, try creating a calendar on them just in case they are the renamed iCloud." I'm not certain if that's a good idea, but it's interesting...

[I have only tried toggling the Calendars setting for iCloud, not actually adding/removing iCloud entirely... I had assumed they would behave the same, but you're right to ask the question because assuming things hasn't worked out so well thus far]

@jamesmontemagno
Copy link
Contributor Author

From my findings, they always put iCloud as the default calendar, event when Google calendar is enabled.

However, I like that approach in the stack overflow. I can implement it today.

In my app I am going to ask them what calendar they want :)

@TheAlmightyBob
Copy link
Owner

Well there's a difference between the user enabling Google calendar and actually setting it as the default calendar. (Settings -> Mail,Contacts,Calendars -> scroll to very bottom -> Default Calendar)

@jamesmontemagno
Copy link
Contributor Author

AHHHH that makes sense then. Blarg, so yeah I think I have an idea of what to do on it now.

@jamesmontemagno
Copy link
Contributor Author

Should be fixed now in latest commit :)

@TheAlmightyBob
Copy link
Owner

Minor note: I said above that the Samsung calendar allowed deleting calendars. I have just learned that they actually removed that capability in recent versions. It also no longer allows creating calendars either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants