Author: Max Mashkov
This repository contains two things:
| Folder | What it is |
|---|---|
PlacesApp/ |
A small SwiftUI test app that lists locations and opens them in Wikipedia. |
wikipedia-ios/ |
A local copy of the official wikimedia/wikipedia-ios app, modified so it can be deep-linked straight to the Places tab centered on a given coordinate. |
The two apps talk to each other over a custom URL scheme (wikipedia://).
Built with Xcode 26 / iOS 26 SDK; PlacesApp targets iOS 26+ and uses Swift
Concurrency, the Observation framework, and MapKit's MKGeocodingRequest.
Out of the box the Wikipedia app can be opened on its Places tab via
wikipedia://places and, optionally, centered on an article
(wikipedia://places?WMFArticleURL=…).
This assignment adds the ability to open Places centered on an arbitrary coordinate supplied by the calling app:
wikipedia://places?lat=<latitude>&lon=<longitude>&title=<optional name>
Example:
wikipedia://places?lat=52.3547498&lon=4.8339215&title=Amsterdam
Opening that URL launches Wikipedia, switches to the Places tab, and centers the map on Amsterdam (loading the top articles around it) instead of the user's current location.
| PlacesApp list | Custom location + map preview | Wikipedia opened at the coordinate |
|---|---|---|
![]() |
![]() |
![]() |
The third screenshot is the modified Wikipedia app after firing
wikipedia://places?lat=52.3547498&lon=4.8339215&title=Amsterdam — it lands on the
Places tab centered on Amsterdam with nearby articles, not the user's location.
A minimal app that demonstrates the feature.
- Fetches locations from
https://raw.githubusercontent.com/abnamrocoesd/assignment-ios/main/locations.jsonusingasync/await. - Shows them in a
List. Some feed entries have no name — those fall back to showing their coordinates. - Tapping a location opens the Wikipedia app at that coordinate.
- The + button lets the user add a custom location (name optional,
latitude/longitude validated). It can also look up a city name and fill in
the coordinates automatically via MapKit geocoding (
MKGeocodingRequest). The added place appears at the top of the list under "Your locations", and the user taps it there to open Wikipedia — the same interaction as any feed location. Custom locations can be removed via swipe-to-delete or the Edit button. - Pull-to-refresh, loading/error states with retry, and a clear alert if the Wikipedia app isn't installed.
MVVM, kept deliberately small and testable:
PlacesApp/
Models/ Location, LocationsResponse (Codable, lat/long → latitude/longitude)
Networking/ LocationsServing protocol + LocationsService (async URLSession)
Deeplink/ WikipediaDeepLink (pure URL builder) + URLOpening abstraction
Geocoding/ Geocoding protocol + MapKitGeocoderService (city name → coordinate)
ViewModels/ LocationsViewModel (@Observable, @MainActor)
Views/ LocationsListView, CustomLocationView
- Swift Concurrency: networking is
async/await; loading is a structured child of SwiftUI's.task, so cancellation propagates. The view model is@MainActorand uses the Observation framework (@Observable). Models areSendable. - Accessibility: each row is a single combined VoiceOver element with a label and an action hint; controls have explicit labels; Dynamic Type is respected.
- Testability: both the network (
LocationsServing) and URL opening (URLOpening) are protocols, so the view model is tested with mocks — no network orUIApplicationneeded.
open PlacesApp/PlacesApp.xcodeprojThen run the PlacesApp scheme on an iOS 26+ simulator. No extra tooling is
required — the .xcodeproj is committed and self-contained.
44 tests across 6 suites, written with the Swift Testing framework
(@Test / #expect):
cd PlacesApp
xcodebuild -scheme PlacesApp -project PlacesApp.xcodeproj \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro' testCovered:
- Model — JSON decoding incl. the entry without a name,
lat/longkey mapping,displayName/coordinate formatting, Codable round-trip. - Networking — real
LocationsServiceagainst a stubbedURLSession(URLProtocol): valid decode, non-2xx status, malformed JSON, transport error. - Deep link —
WikipediaDeepLinkURL construction (scheme/host, query items, title encoding, locale-independent decimals). - View models — feed loading (success/failure), open behavior, add-to-list +
de-duplication, coordinate validation, and MapKit geocoding — all with mocks, so
no network or
UIApplicationis touched.
The Wikipedia-side change is also covered by unit tests — see Part 2.
The change follows the app's existing deep-link pipeline
(NSUserActivity → WMFAppViewController → PlacesViewController). Four files:
-
Wikipedia/Code/NSUserActivity+WMFExtensions.m—wmf_placesActivityWithURL:now also parseslat,lon, and optionaltitlequery items and, when a valid coordinate is present, stashes them in the activity'suserInfo(WMFLatitude/WMFLongitude/WMFLocationName). Parsing uses anen_US_POSIXnumber formatter so.-separated decimals are always accepted. -
Wikipedia/Code/WMFAppViewController.swift— the.placescase ofprocessUserActivityreads that coordinate and, when present, calls the newPlacesViewController.showLocation(withLatitude:longitude:name:)instead of the article-based path. -
Wikipedia/Code/PlacesViewController.swift— newshowLocation(withLatitude:longitude:name:). It builds a 10 km region around the coordinate, sets the map region, and runs a location search there. It also setspanMapToNextLocationUpdate = falseso the first Core Location update does not snap the map back to the user's location. This mirrors the existingzoomAndPanMapView(toLocation:)+performDefaultSearch(withRegion:)behavior. -
docs/url_schemes.md— documents the new coordinate deep link.
The change is unit-tested in the app's own test target:
WikipediaUnitTests/Code/NSUserActivity+WMFExtensionsTest.m adds cases for the
lat/lon/title parsing (valid, negative, no-title, incomplete-coords-ignored).
cd wikipedia-ios && scripts/setup_bundle_id ci
xcodebuild test -scheme Wikipedia -project Wikipedia.xcodeproj \
-destination 'id=<booted-sim-udid>' -only-testing:WikipediaUnitTests/NSUserActivity_WMFExtensions_wmf_activityForWikipediaScheme_Test \
CODE_SIGNING_ALLOWED=NOOne-time signing config (safe defaults, no prompt), then build:
cd wikipedia-ios && scripts/setup_bundle_id ciTo just compile, CODE_SIGNING_ALLOWED=NO is fine. To actually run it, the
app needs its app-group entitlement applied or it crashes on launch in
MWKDataStore (the shared container resolves to nil). Ad-hoc signing is enough
on the simulator:
xcodebuild -scheme Wikipedia -project Wikipedia.xcodeproj \
-destination 'id=<booted-sim-udid>' \
CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=YES buildThen install the built .app, launch it, skip onboarding, and fire the deep link:
xcrun simctl openurl booted "wikipedia://places?lat=52.3547498&lon=4.8339215&title=Amsterdam"(From SpringBoard/simctl, iOS shows a one-time "Open in Wikipedia?" prompt — tap
Open. The result is the third screenshot above.)
- Clone the Wikipedia app and modify it so it can be deep-linked to the Places
tab at a given coordinate (
wikipedia://places?lat=..&lon=..) - Test app fetches locations from the JSON feed
- Tapping a location calls Wikipedia the new way
- User can enter/add a custom location and open Wikipedia there
- SwiftUI for the Places app
- ReadMe
- Unit tests (44 Places + 10 Wikipedia)
- Bonus — Swift Concurrency & Accessibility
- Worked locally with git; shared as a public GitHub repo
- The assignment brief lists the feed URL under the
assignmentiosrepo, but the file is actually served fromassignment-ios(with a hyphen) — that is the URL the app uses. wikipedia-ios/is a vendored copy of the upstream app at clone time; the deep-link feature is the only functional change. Upstream lives at https://github.com/wikimedia/wikipedia-ios.


