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

[New] Generate offline map #31

Merged
merged 33 commits into from
Aug 1, 2022
Merged

[New] Generate offline map #31

merged 33 commits into from
Aug 1, 2022

Conversation

clee088
Copy link
Contributor

@clee088 clee088 commented Jun 24, 2022

Description

This PR implements Generate offline map in Maps category.
URL to README: URL

Linked Issue(s)

  • common-samples/issues/3624

How To Test

  1. Pan around the map to the area of interest you would like to be taken offline.
  2. Tap the "Generate Offline Map" button and wait.
  3. Tap the cancel button to test cancellation.

Screenshots

generate-offline-map-demo.mp4

To Discuss

  1. Temporary job progress view
  2. Viewpoint/Area of Interest: The viewpoint of the offline map is not centered, similar to the download vector tiles sample. The method of displaying the area of interest could also be improved--sometimes the red box doesn't show when the sample loads.
  3. Map rotation is disabled for similar reasons as the download vector tiles sample.

@clee088 clee088 requested a review from yo1995 June 24, 2022 17:45
Copy link
Collaborator

@yo1995 yo1995 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we briefly mentioned, view model could be better for this sample.
I think we may need to jot down the criteria/threshold in the wiki on when to make it a view model, after finish reviewing the recent PRs.

Shared/Samples/Generate offline map/README.md Outdated Show resolved Hide resolved
offlineMap = output.offlineMap

// Sets the initial viewpoint of the offline map.
offlineMap?.initialViewpoint = Viewpoint(targetExtent: areaOfInterest.expanded(by: 0.8))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

offline-map-tiles.mp4

To other reviewers: There seems to be an API bug for the generated offline map, will need 👀 from other reviewers. When the map is zoomed out with 2 fingers, it sometimes shows a larger extent than the red box. It seems that additional basemap tiles are included.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue logged at swift/issues/2008

Copy link
Collaborator

@yo1995 yo1995 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems sth is holding up the model when the view disappears/sample quits. When I enter the sample multiple times, it holds multiple instances of the model. I'll need to take another look tomorrow.

@yo1995
Copy link
Collaborator

yo1995 commented Jul 19, 2022

It seems sth is holding up the model when the view disappears/sample quits. When I enter the sample multiple times, it holds multiple instances of the model. I'll need to take another look tomorrow.

I have experimented for quite a while and still could not figure out the root cause.

3 samples that uses view models currently:

  • Find route: It doesn't release the view model even if the sample view has disappeared
  • Generate offline map: same
  • Show device location: same

Set surface placement mode: The view model is released

My observation is that the view model in Set surface placement mode sample doesn't have any async task involved. So I'm guessing something is off in the async part of these samples. I'll move on and keep reviewing the other parts of the code.

@clee088
Copy link
Contributor Author

clee088 commented Jul 19, 2022

I think the root cause of the memory leak may lie within the alert modifier; more specifically, the isShowingAlert Boolean. When commenting out the .alert(...) modifier, the view model seems to be released from memory (although only when another sample is navigated to). Also, when swapping out the $model.isShowingAlert with a state Boolean, the view model also is deallocated. I'm not exactly sure why this is the cause so I'll look more into it for the rest of the day.

Also, I was wondering when is the observable object supposed to be released from memory? When I return to the list of samples, the view model is still in memory until I either navigate to the same sample, where it is released and initialized again, or I navigate to a different sample.

@yo1995
Copy link
Collaborator

yo1995 commented Jul 19, 2022

I think the root cause of the memory leak may lie within the alert modifier; more specifically, the isShowingAlert Boolean. When commenting out the .alert(...) modifier, the view model seems to be released from memory (although only when another sample is navigated to). Also, when swapping out the $model.isShowingAlert with a state Boolean, the view model also is deallocated. I'm not exactly sure why this is the cause so I'll look more into it for the rest of the day.

Hmm this is quite 🤯 . Thanks for pointing this out. I'll give it another try on Xcode 14 beta.

Also, I was wondering when is the observable object supposed to be released from memory? When I return to the list of samples, the view model is still in memory until I either navigate to the same sample, where it is released and initialized again, or I navigate to a different sample.

This is an expected behavior, but not ideal. IMO It's due to the split screen navigation style. When exit from a sample, the view is not released until a new sample is selected. (think of an iPad) We discussed about this before in the old sample viewer but couldn't figure out a better way. 😕

@yo1995
Copy link
Collaborator

yo1995 commented Jul 19, 2022

I think the root cause of the memory leak may lie within the alert modifier; more specifically, the isShowingAlert Boolean. When commenting out the .alert(...) modifier, the view model seems to be released from memory (although only when another sample is navigated to). Also, when swapping out the $model.isShowingAlert with a state Boolean, the view model also is deallocated. I'm not exactly sure why this is the cause so I'll look more into it for the rest of the day.

With some workarounds of the build phase bug, I tested it on Xcode 14 and iOS 16, and the models are no longer held. So I'm happy to let it slide for now as an iOS bug 😬

Copy link
Collaborator

@yo1995 yo1995 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with the comments above and below. Don't forget to solve merge conflict.

Cancels the generate offline map job when the view disappears and moves removing the temporary directory into deinit.
@clee088
Copy link
Contributor Author

clee088 commented Jul 20, 2022

I also prefer handling the removal of temporary files in the view model, especially with the sample README and source code viewer. There seems to be a work around of the alert memory leak by receiving changes of the view model's error, and setting a local state variable to whether or not the error equals nil. This allows temporary files to be removed when the view model is released from memory.

Another thing I saw is that the generate offline map job is not cancelled when the view disappears, causing the view model to exist until the task is complete, even if the sample is not being viewed. Ideally the cancellation code would go in the deinit, but I can't figure out/don't know if it is allowed to have a task within the deinit. For now, it's implemented in the onDisappear modifier, which will cause the download task the cancel when the README viewer is presented while downloading.

@clee088 clee088 requested a review from yo1995 July 20, 2022 16:43
yo1995
yo1995 previously approved these changes Jul 20, 2022
Copy link
Collaborator

@yo1995 yo1995 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the efforts! 💯

@yo1995 yo1995 requested a review from philium July 20, 2022 23:12
Comment on lines +38 to +40
.onDisappear {
Task { await model.cancelJob() }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, it's implemented in the onDisappear modifier, which will cause the download task the cancel when the README viewer is presented while downloading.

When the sample info view is implemented, if the visibility state of that view were passed down through the environment, then a check for that could be added here:

guard !isSampleInfoViewVisible else { return }

clee088 added a commit that referenced this pull request Jul 27, 2022
Comment on lines +80 to +82
Button("Generate Offline Map") {
isGeneratingOfflineMap = true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That still seems bright to me.

@clee088 clee088 merged commit d4b0796 into v.next Aug 1, 2022
@clee088 clee088 deleted the clee/New-GenerateOfflineMap branch August 1, 2022 13:43
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

Successfully merging this pull request may close these issues.

None yet

3 participants