Learn Swift interactively on your iPhone.

Overview

Unwrap logo

Twitter: @twostraws

Unwrap is an app that helps you learn Swift faster and more effectively.

At its core lies almost 100 video lessons that teach all the fundamentals of the Swift programming language, with each lesson backed up by an interactive review.

Once you’ve made some progress learning, you can dive into a selection of practice activities that make you write code by tapping, dragging, or typing, find errors, predict program output, and more. There are also daily challenges that test your overall language knowledge once per day, helping your new skills really sink in.

Unwrap app is available to download for free on the App Store. I’ve made the code available so that anyone who wants to can see how I structure my code and perhaps learn from it. If you’d like to help you’re most welcome to and there are many opportunities, but make sure you read the contribution guidelines first.

Trying it yourself

Unwrap is written using Xcode 10.2 and Swift 5.0. All the CocoaPods are checked in to this repository, so you should be able to clone this and build it immediately by opening Unwrap.xcworkspace.

As far as I know the app is feature complete, but there are likely to be errors all over the place at least to begin with – if you hit problems, either building or running the app, please let me know.

Contribution guide

Any help you can offer with this project is most welcome, and trust me: there are opportunities big and small, so that someone with only a few weeks of Swift experience can help.

However, before you start please read the LICENSE.md and CONTRIBUTING.md files. Although all the source code of Unwrap is available under the MIT license, the assets are not redistributable – please see the license for more detail.

If you’d like to help, here are some suggestions ordered from most easy to most difficult. I’ve added documentation to most if not all of the code, but there’s also a separate document in this repository called CONTRIBUTING.md that documents how the code is structured and how it works.

Easy

  1. Just try running the app and let me know if you hit any problems.
  2. I’ve written a huge amount of all-new content for this app, so if (and when!) you see any typos please correct them and open a PR.
  3. If you spot any redundant code, or code that repeats itself that can sensible be refactored not to repeat, you’re welcome to clean it up. Any unused code should be deleted rather than just commented out.
  4. If you can write (sensible!) solutions for Free Coding problems that aren’t currently accepted, please add them.
  5. If you see any Sixty Seconds chapters that don’t have a postscript (alert message shown between the chapter text and review), and you think there’s something important to add there, add it.
  6. Write new tests. It doesn’t matter how small they might seem, tests are always appreciated and won’t require you to modify any of the core code.

Intermediate

  1. If you find any bugs and can fix them, by all means do.
  2. If you spot any performance hotspots that can be resolved smoothly, go for it.
  3. All the practice activities have their data stored as JSON. I’ve tried to create samples of each of them, but it would be awesome to add more.
  4. Right now the app is available only in English. We could look at localizing all the text, but I have concerns partly because Swift continues to change and partly because the videos will get in the way. If you have suggestions, let me know!
  5. Did I already mention adding tests?

Advanced

  1. Although I’m pretty happy with the app’s architecture, it could always be improved – if you have suggestions, let me know!
  2. I’ve added the basics of theme support, but it’s not implemented or tested yet. This could be expanded to work everywhere, and new themes could be added.
  3. The storyboard started off small and grew far too big for its boots. This is particularly annoying because many screens are similar. Some of the UI is now built in code already. To resolve this we could switch to building even more UI in code, starting with a direct copy of the storyboard, then try to refactor it so that similar view controllers are created using shared code.

Again, please make sure you read the LICENSE.md and CONTRIBUTING.md files before you start just to avoid problems.

Credits

Unwrap was designed and built by Paul Hudson. Hacking with Swift, Swift in Sixty Seconds, Unwrap, and the Unwrap logo are all copyright © Paul Hudson 2019.

Unwrap is built using some third-party frameworks and fonts: DZNEmptyDataSet, Font Awesome, MKRingProgressView, QuickLayout, SDWebImage, Sourceful, Zephyr, and SwiftEntryKit. Their licenses are stored inside their respective Pods directories, and are repeated inside the app’s credits screen.

Swift, the Swift logo, Xcode, Instruments, Cocoa Touch, Touch ID, AirDrop, iBeacon, iPhone, iPad, Safari, App Store, watchOS, tvOS, Mac and macOS are trademarks of Apple Inc., registered in the U.S. and other countries.

Unwrap includes an iMessage sticker pack that incorporates a variety of logos from around the Swift community – these are used with permission, and we're grateful to each person or project for granting that permission:

If you liked Unwrap and want more like it, I have a whole website full of free Swift tutorials.

Comments
  • Problem in a Daily Challenge question #50

    Problem in a Daily Challenge question #50

    Fixes that the constants created do not match the constants used when summing.

    Is there a way to test this? The son file is loaded than shuffled? What are the thoughts on having a debug mode that would load and show all the questions? Something as simple as having a long press on the "Predict the Output" button.

    opened by mike011 11
  • Added 2 new answers for a Free Coding Question.

    Added 2 new answers for a Free Coding Question.

    Added 2 new answers for a Free Coding Question, in which user has type code that doubles all the elements of an array.

    I'm working to add 4-5 more new answers to the same question.

    opened by heyrahulrs 10
  • Typo:

    Typo: "by", expected: "be"

    Addresses #213

    I have fixed SwiftLint warnings. I also resolved an issue with Extension tests:

    • cleanString6.toAnonymizedVariables() is compared to anonymizedString6
    • the expression returns "..." and is compared with " ... "
    • I have changed the anonymizedString6 value from " ... " to "..."

    Tested on:

    • iPhone 12 Simulator
    • iOS version 15.0
    opened by erikdrobne 9
  • Persist User state on NSUbiquitousKeyValueStore

    Persist User state on NSUbiquitousKeyValueStore

    Since the app is now universal,I wanted to be able to persist user progress between devices. I have tried to accomplish this with NSUbiquitousKeyValueStore, using the same logic @twostraws built into the app for saving to UserDefaults. Its 99% there.

    The last issue is, and I hope that you can help steer me into the correct direction to resolve this, that when the app is open on two devices at the same time, the trailing device is not updating its UI in response to NSUbiquitousKeyValueStore.didChangeExternallyNotification being observed. Ideally, because having two devices with the app open at the same time is a real probability, the not in use device should update and refresh its tableviews to correspond with the values saved in NSUKVS. Currently, the data is received but the UI does not reflect newest changes. However, if you exit and restart the app, the newest changes will be visible.

    How should I refresh the data to display on the inactive device without exiting the app? reloadData doesn't do anything and I have tried a couple different AppDelegate functions without success. I suspect it has to do with the coordinator pattern being used. I have a couple videos on that subject to watch tomorrow but in the meantime...

    opened by wayni208 9
  • Tour grammar fix

    Tour grammar fix

    Hopefully this works as intended, I am very much a newbie: am trying to submit a small grammar fix for the Tour JSON and not submit the project files changed to allow me to build locally. Please help me learn how to do this better :)

    opened by SuzGupta 6
  • NewsDataSource - Unexpected nil User

    NewsDataSource - Unexpected nil User

    First off, I want to say that the app looks awesome! 😃 I ran into a compilation issue on the way to work that I thought I would file here. I might just be missing something so I apologize in advance if that's the case.

    Hardware

    • Xcode 9.3
    • iPhone X Simulator (11.4)

    Error

    I see the following error:

    Fatal error: Unexpectedly found nil while unwrapping an Optional value
    

    for this line

    // NewsDataSource.swift
    var containsNewArticles: Bool {
        get {
            if let newestArticleID = articles.first?.id {
                // This line here
                if newestArticleID > User.current.latestNewsArticle {
                    return true
                }
            }
         set {
        ....
    }
    

    Possible Solution

    A quick fix I added to get the app to compile is to conditionally unwrap the User.current as so:

    if let user = User.current, newestArticleID > user.latestNewsArticle {
    

    However, I think it would help to understand why User.current was nil in the first place to see if this is the best fix. There are other places where User.current is being used so it could possibly affect other areas.

    opened by ajfigueroa 6
  • Dealing with the '…' ellipsis issue by homogenising to three periods

    Dealing with the '…' ellipsis issue by homogenising to three periods

    I hope I've done this right. I've largely followed the pattern of other similar homogenising blocks so hopefully it is ok. If not, would be interesting to see where I've made mistakes.

    opened by robinlmp 4
  • Remove level-up chime to prevent background audio interruption

    Remove level-up chime to prevent background audio interruption

    Currently, the level up chime completely stops any music/podcast I have playing in the background.

    This pull request resumes the background audio after the chime has finished playing.

    p.s: I considered using the .mixWithOthers category option to have both the chime and background audio play simultaneously, but this is not optimal for the videos

    opened by almaleh 4
  • Localization

    Localization

    I saw some user-facing strings that are not wrapped in an NSLocalizedString and I was wondering about the plans of localizing the app?

    It might be a good idea to prepare for that, and it could be a nice task to get an overview of the code base. :)

    (I might want to pick this one up myself 😄)

    opened by BasThomas 4
  • Show unread badge on reused cells in the NewsViewController

    Show unread badge on reused cells in the NewsViewController

    This PR fixes an issue with the blue badges added in #103 whereby reused cells would sometimes show the incorrect badge state because the badge state was not reset on reused cells.

    opened by julianschiavo 4
  • Make it a universal app

    Make it a universal app

    It feels so much better when you can use an iPhone app on an iPad as well. If there are no bigger concerns why this app shouldn't allow universal builds then I like the user to decide which device fits best to use the app.

    #29

    opened by lunij 4
  • Infinite score in challenges.

    Infinite score in challenges.

    Somehow I got into a state on my iPad where I could keep clicking "Continue" and it would add the challenge score to my total.

    So after tapping "continue" the screen doesn't change. So I hit the Continue button again and saw that it was increasing my total progress. Then I just hit the "Continue button as fast as I could and boom I got over a million points.

    Steps to reproduce

    I have no idea how I got here. I just did the challenge. I was working on it in bed and fell asleep then woke up and kept going. Now I can get infinite points.

    Expected behavior

    When I hit continue it would score and then at least deactivate the "Continue" button. Or it would take me to another screen saying I needed to wait a day for the next challenge.

    I'm not sure how this is supposed to work so I was just playing around with the app. There are a few different UX paths this could take.

    Actual behavior

    Here is a video of the behavior.

    Environment

    • iOS Version:
      • 15.2
    • Unwrap App Version:
      • 1.5
    • Device:
      • iPad 9th gen
    opened by td-gonzales 0
  • WebViewController: Actually display back/forward/share buttons

    WebViewController: Actually display back/forward/share buttons

    Upon fixing #232, I discovered it actually was all already in there, so all I did was display the buttons. If there was a reason for not displaying them, please tell me, so I can try to do it right.

    Works fine for me in simulator, and no new failing tests or linting errors due to my commit.

    opened by d12bb 1
  • Add share menu and open in Safari to articles in news section

    Add share menu and open in Safari to articles in news section

    The news section in this app is quite limiting as one has to read an article in the app. It would be great if one could open them in the browser, or it had a share menu to send it to other apps for reading later or sharing on social media

    Steps to reproduce

    1. Go to News section
    2. Tap on article
    3. See there's no button other than reload

    Expected behavior

    1. Have two buttons for opening in Safari and sharing
    opened by d12bb 0
  • Local Notification support for Daily Challenges?

    Local Notification support for Daily Challenges?

    I've been trying to get a streak going but every so often I forget to open the app so daily reminders could be of use — is this a worthy improvement I could work on that others would like?

    I'm thinking something really simple like choosing what time you want the notifications to trigger and then that's it 😊 perhaps a "Configure Notifications" cell in the Challenges table or something, that presents/pushes a new view controller

    opened by SunburstEnzo 0
  • Opening app on M1 Mac resets progress

    Opening app on M1 Mac resets progress

    The problem

    It seems that if the app is opened on an M1 Mac, that the users progress is reset. I haven’t tried it myself, mainly because I don’t use an M1 (yet).

    Reported on the slack channel here: https://hackingwithswift.slack.com/archives/CJBQQ7J4C/p1634786078000800

    Expected behaviour

    I suppose either the app should be set to not target macOS, or it should not wipe progress when it is installed.

    Unsure which versions were being used. Have asked and will update when I get a reply.

    opened by robinlmp 0
  • Accessibility: Add better label to section video play buttons

    Accessibility: Add better label to section video play buttons

    From a user: "There is a “link” that plays the video for the section, but from an accessibility point of view all that is spoken is “link”. Could you consider adding a label like “Play Video” so that the Voiceover speaks “Play Video link”. "

    good first issue 
    opened by twostraws 0
Owner
Paul Hudson
Creator of Hacking with Swift, author of books about iOS, macOS, watchOS, and tvOS, public speaker, Rubik's cube enthusiast, and herder of my kids.
Paul Hudson
📱 Wire for iOS (iPhone and iPad)

Wire™ This repository is part of the source code of Wire. You can find more information at wire.com or by contacting [email protected]. You can find

Wire Swiss GmbH 3.2k Jan 8, 2023
TriangleDraw is a pixel editor for iPad and iPhone.

TriangleDraw TriangleDraw is brilliant for sketching logos. You can quickly create designs that can be used for branding on letterheads or on your web

TriangleDraw 46 Sep 26, 2022
PHPHub for iOS is the universal iPhone and iPad application for PHPHub

PHPHub is a Forum project written in Laravel 4.2, and it is also the project build up PHP & Laravel China community. PHPHub for iOS is the universal i

Aufree 1.2k Nov 18, 2022
Swift Library based on AVFoundation that allow to easily add camera feature with custom UI into your project.

Would you like to create your camera same as Snapchat or Instagram? I think this library could help you. Basicly it is a wrapper above AVFoundation th

Taras Chernyshenko 14 Sep 21, 2022
A calculator for your Apple Watch but only if you have fingers small enough to press the buttons.

AppleWatchCalculator A calculator for your Apple Watch but only if you have fingers small enough to press the buttons. A very simple calculator on you

Patrick Balestra 148 Dec 21, 2022
Firefox for iOS, branch works with Xcode 12.5.1, Swift 5.4.2 and supports iOS 11.4 and above.

Firefox for iOS Download on the App Store. This branch (main) This branch works with Xcode 12.5.1, Swift 5.4.2 and supports iOS 11.4 and above. Please

Mozilla Mobile 11.2k Jan 7, 2023
Fully open source text editor for iOS written in Swift.

Edhita Fully open source text editor for iOS written in Swift. http://edhita.bornneet.com/ What Edhita means? Edhita (Romaji) == エディタ (Katakana) == Ed

Tatsuya Tobioka 1.2k Jan 7, 2023
30 mini Swift Apps for self-study

Swift 30 Projects Contents This repo is updated with Swift 5 and compatible with iPhone X: Simple UIKit components UIScrollView, UITableView, UICollec

Soap 7.5k Jan 3, 2023
A Hacker News reader in Swift

SwiftHN A Hacker News reader in Swift using the best features of both the language and iOS 8 latest API (well, that's the end goal) SwiftHN is now ava

Thomas Ricouard 1.7k Dec 24, 2022
Build a Swift App as a designer

DesignerNewsApp Simple iOS client for Designer News, by the creator of Design+Code and the team, written in Swift. Usage Download the repository $ git

Meng To 2.4k Dec 24, 2022
swift implementation of flappy bird. More at fullstackedu.com

FlappySwift An implementation of Flappy Bird in Swift for iOS 8. Notes We're launching a course Game Programming with Swift If you are interested in e

newline (formerly Fullstack.io) 9.5k Dec 29, 2022
Basic app to show how to login with Facebook, Google, Twitter. Created for learning purpose :) using Xcode 9 and Swift 4.0

Social Logins iOS Basic app to show how to login with Facebook, Google, Twitter. Created for learning purpose :) using Xcode 9 and Swift 4.0 Note: Bef

Jogendra 12 Nov 4, 2022
Applozic UI Kit in Swift

Official iOS Swift SDK for Chat ?? Introduction ?? Applozic brings real-time engagement with chat, video, and voice to your web, mobile, and conversat

Applozic 50 Mar 21, 2022
Simple sample of using the VIP (Clean Swift) architecture for iOS

MyAnimeList Simple sample of using the VIP (Clean Swift) architecture for iOS. ViewController: controls the event handling, view life cycle and displa

null 24 Oct 12, 2022
Swift audio synthesis, processing, & analysis platform for iOS, macOS and tvOS

AudioKit AudioKit is an audio synthesis, processing, and analysis platform for iOS, macOS (including Catalyst), and tvOS. Installation To add AudioKit

AudioKit 9.5k Jan 5, 2023
2048 for Swift

swift-2048 A working port of iOS-2048 to Apple's new Swift language. Like the original Objective-C version, swift-2048 does not rely upon SpriteKit. S

Austin Zheng 3.1k Dec 24, 2022
▶️ video player in Swift, simple way to play and stream media on iOS/tvOS

Player Player is a simple iOS video player library written in Swift. Looking for an obj-c video player? Check out PBJVideoPlayer (obj-c). Looking for

patrick piemonte 2k Dec 24, 2022
SushiMarketingApp - Sushi Marketing App Built With Swift

SushiMarketingApp Sushi E-Commerce App Language: Swift and Objective-C Database:

Serkan Kara 3 Apr 16, 2022
TwitchIRC - A Swift package for parsing/serializing Twitch IRC messages

TwitchIRC A Swift package to take of parsing/serializing Twitch IRC messages for

Mahdi Bahrami 8 Jan 3, 2023