Open-source project
mzeeshanid/MZDownloadManager avatar
mzeeshanid/MZDownloadManager

MZDownloadManager: a URLSession wrapper for background downloads in Swift

This download manager uses NSURLSession api to download files. It can download multiple files at a time. It can download large files if app is in background. It can resume downloads if app was quit.

1,118 stars234 forksSwiftBSD-3-Clause

At a glance

What is it?
MZDownloadManager is a small Swift library that puts a model, a delegate and a task list around the URLSession download API, so an app can download several files at once, keep going in the background, pause, resume an interrupted transfer and retry after an error. It suits anyone who needs more than a one line data task, and it asks for an iOS 9 deployment target and a server that supports resuming.
Who is it for?
Adopt MZDownloadManager if your iOS app needs a queue of downloads that survive the app being backgrounded or killed, because the bookkeeping around resume, retry and the download model is the part you would otherwise write yourself. Do not adopt it for a single small file, where a plain URLSession download task is less code.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 44 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the library wraps, and what it adds

MZDownloadManager is a download manager for iOS that uses the URLSession API to download files, and the feature list is short enough to state in full.

It can download large files if the app is in the background, and it can download files if the app is in the background. It can download multiple files at a time. It can resume interrupted downloads. The user can pause a download. And the user can retry any download if an error occurred during the download.

That list reads like a set of things you would have to add yourself if you used URLSession directly, and that is the point of the library. The raw download task API is easy. The parts that are work are the ones around it. A paused download has to keep its state somewhere. A resumed download has to know how many bytes were already on disk. A retry has to decide whether to start over or to continue. A background transfer has to be reattached when the app comes back to the foreground, because the system terminated the app in the meantime and the transfer continued without it.

The library gives you a model per download, a delegate protocol for the results, and a manager object that owns the session, so the application code deals with a list of downloads rather than with a session and a delegate queue.

It is distributed through CocoaPods and through Swift Package Manager, and the licence is BSD. The author is Muhammad Zeeshan, and the project is used in his own MZFileManager application.

Background transfers, and why the requirements matter

Two requirements in the documentation decide whether this library can work in your case.

The first is that the minimum deployment target is iOS 9, with Xcode 8 named in the requirements section. For a library being considered in 2026, that is a floor rather than a problem, since any current deployment target is above it, and the practical effect is that the library has no modern platform requirements to satisfy.

The second requirement is the one that matters at runtime, and it is a server side property rather than a client side one: for resuming downloads, the server must have resuming support.

That is a hard constraint and it is worth being clear about why. A resumed download is a request that asks the server to start sending from a byte offset rather than from the beginning, and the server has to agree. Servers that do not support range requests will either ignore the offset and send the whole file again, or refuse the request. A download manager cannot work around that, because the client has no way to ask for the middle of a file that the server will not serve in pieces.

So the first question for an integrator is not about the library at all, it is whether the URLs you intend to fetch come from a server that supports range requests. For a file on a modern web server or a cloud object store, this is usually the case, and for an exotic source it may not be.

The retry behaviour is worth pairing with this, since the two features share a cause. A download that fails halfway is resumable if the server allows it and restartable if it does not, and the library offers both.

Installing it through CocoaPods or Swift Package Manager

There are two supported routes, and the README gives the exact steps for each.

For CocoaPods, you add one line to your Podfile.

ruby
pod "MZDownloadManager"

For Swift Package Manager, the instructions are for Xcode 11 and later, where you select File, then Packages, then Add Package Dependency, and enter the project URL.

The project URL is the GitHub repository for MZDownloadManager, and the package manifest is in the repository root as Package.swift, alongside a podspec and an Xcode project for the library itself. There is a Sources directory for the code and a Tests directory, which tells you the project is laid out as a Swift package with a test target, not as a script dropped into an app.

The example project is a separate thing, and it comes with its own CocoaPods setup. To run it you clone the repository and run pod install from the Example directory first, which is the standard CocoaPods requirement for a project that has a workspace rather than a plain project file. The Example directory holds a workspace, a Podfile and a Podfile.lock alongside the example sources, which is what a CocoaPods example project looks like in practice.

Both distribution routes are still maintained in the repository, and the CocoaPods badge in the README header is pointed at the pod page, so the library is discoverable where iOS developers look for it.

Downloading to a custom path, and the delegate contract

The update section of the README describes a newer addition, a set of helper functions to support downloading to a custom path, with the example project updated to show the usage.

The method takes the file name, the source URL and the destination path.

swift
public func addDownloadTask(fileName: String, fileURL: String, destinationPath: String)

What happens on completion is the part that needs care, because there are two outcomes and the documentation spells out both.

If the destination folder still exists, the downloaded file is moved to the specified destination and the success delegate method is called. If the destination folder does not exist, a different delegate method is called, which gives the application an opportunity to handle the downloaded file appropriately, and it receives the download model, an index and the location of the file.

swift
optional func downloadRequestDestinationDoestNotExists(downloadModel: MZDownloadModel, index: Int, location: NSURL)

And if that delegate method is not implemented, the library just calls the failure method.

That fallback is the detail to notice. A developer who adds a custom path and forgets the optional delegate gets a failure callback for a download that actually succeeded. The file is on disk and the application is told it failed, and the fix is to implement the one optional method.

The delegate is also optional in the sense that it is a protocol method, so the failure path is the default rather than an error case, which is a reasonable default for a library but a sharp edge for the caller.

The threading detail and how the example uses it

There is one warning in the delegate section, and it is the kind that saves an afternoon.

The delegate method will be called on the session's queue.

This is the standard behaviour of a URLSession delegate, and it is the sort of thing that is easy to forget when the rest of the code runs on the main queue. An application that updates a progress view from that callback without hopping to the main queue will have intermittent visual glitches that are hard to reproduce, and a developer who has never seen a session delegate may spend a day on it.

The example project is the place to see the intended usage, and the README's update note points at it explicitly, saying the example project is updated about the usage of the new helpers. Reading an example that has been kept in step with the API is more reliable than reading the API documentation alone.

The project also has a test target, MZDownloadManagerTests in the repository root, and a Travis configuration for continuous integration. For a library whose interesting behaviour involves the system backgrounding an app mid transfer, having tests is useful, and the continuous integration badge in the README header shows the build was wired up.

The state of the project and who should look at it

Two facts about the state of the project are worth putting side by side.

The last push to the repository was on 2026-09-09, and the only release listed for the project is version 3.3 from 2017-04-27, described as bug fixes and improvements. So the code is being worked on in the repository, but the version history stops in 2017.

That combination is common with a small iOS library that is stable, and it does not mean the project is abandoned. The changes since then are visible in the README, since the update section describes new helper functions for custom download paths, and the requirement list mentions Xcode 11 for the Swift Package Manager route, which is a 2019 technology and therefore a later change than the 2017 release.

So the reasonable reading is that the library continues to receive fixes and small features, and that the released version number is not a reliable guide to what the repository contains.

The practical guidance for an integrator is unchanged either way. If you need a download queue with background transfer, pause, resume and retry, and your server supports range requests, this library has those things and is small enough to read. If you need something it does not do, such as a download queue shared across several processes, or progress reporting to a server, or encryption of the downloaded content, then the URLSession API is the thing to read next.

And for anyone who wants to see it in a real application, the author points at MZFileManager, which is a live app built on the library, with a page describing its features. A production app is a better test of a download manager than any example project, because the interesting failures only happen when a device is locked, the app is killed, or the network drops.

Editorial conclusion

Adopt MZDownloadManager if your iOS app needs a queue of downloads that survive the app being backgrounded or killed, because the bookkeeping around resume, retry and the download model is the part you would otherwise write yourself. Do not adopt it for a single small file, where a plain URLSession download task is less code. Before you integrate, check that your server supports range requests, since the documentation states that resuming depends on the server having resuming support, and read the delegate contract for custom paths, because the fallback behaviour when a delegate is not implemented is a failure callback rather than a default move.

Frequently asked questions

What does MZDownloadManager do?

It is a download manager for iOS that uses the URLSession API to download files. It can download large files and continue downloading when the app is in the background, download multiple files at a time, resume interrupted downloads, let the user pause a download, and retry any download that failed.

How do I add MZDownloadManager to my project?

With CocoaPods, by adding pod "MZDownloadManager" to your Podfile, or with Swift Package Manager, where in Xcode 11 or later you select File, then Packages, then Add Package Dependency and enter the project URL. To run the example project, clone the repository and run pod install from the Example directory first.

What are the requirements for MZDownloadManager?

Xcode 8 and a minimum deployment target of iOS 9, and for resuming downloads the server must have resuming support. The library is available under the BSD licence through CocoaPods and through Swift Package Manager.

How does MZDownloadManager handle a download to a custom path?

You call addDownloadTask with the file name, the source URL and the destination path. On completion it checks whether the destination folder still exists, moves the file and calls the success delegate if it does, and if it does not it calls the optional downloadRequestDestinationDoestNotExists delegate, or the failure method if that delegate is not implemented. The delegate is called on the session's queue.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. mzeeshanid/MZDownloadManager on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mzeeshanid-mzdownloadmanager.svg)](https://hysenlabs.com/projects/mzeeshanid-mzdownloadmanager)

Was this useful?