J’s Helper

A collection of Swift functions, extensions, and SwiftUI and UIKit Views.

Legend:

  • ? UIKit
  • ? SwiftUI
  • ? Shared

Installation

  1. In XCode 12 go to File -> Swift Packages -> Add Package Dependency or in XCode 13 File -> Add Packages
  2. Paste in the repo’s url:
https://github.com/JemAlvarez/JsHelper

Import

JsHelper

import JsHelper

Onboarder

import Onboarder

UIKit

? Add constraints on all anchors for a view

yourSubview.addConstraints(equalTo: yourParentView)

? Setup UIKit with no Storyboards

  1. Add the following code in SceneDelegate
  2. Follow steps in makeWindow function documnetation

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
	if let window = makeWindow(for: scene, with: ViewController()) {
		self.window = window
	}
}

? Get hex string from UIColor

UIColor.blue.getHexString()

? Initialize UIColor from hex string

UIColor(hex: "#000000")

SwiftUI

? Get hex string from Color

Color.blue.getHexString()

? Initialize Color from hex string

Color(hex: "#000000")

? Get current UIWindow

if let window = UIApplication.shared.currentUIWindow() {
	// handle ui window
}

? Present Share Sheet

Button("Present Sheet") {
	presentShareSheet(with: ["Strings", Images, URLs])
}

? Request AppStore Review

Button("Request Review") {
	requestReview()
}

? Open Link

@Environment(\.openURL) var openURL

Button("Open Link") {
	// Takes in an `OpenURLAction` doesn't have to be `openURL`
	openLink("https://apple.com", with: openURL)
}

? Give view radius on custom corners

yourView
	.cornerRadius(50, corners: [.bottomLeft, .topRight])

? Get View size (width & height)

yourView
	.getViewSize { width, height in
		// Now you can add your width and height to your state and use it
	}

? Haptic feedback

Button("Haptic") {
	// Default HapticStyle is `soft`
	haptic()
	// Other HapticStyles: light, medium, heavy, rigid, soft, success, error, warning, selection
	haptic(.heavy)
}

? Guage Progress View

ProgressView("Progress", value: 69, total: 420)
	.progressViewStyle(
		GaugeProgressViewStyle(
			strokeColor: .red, 
			strokeWidth: 15, 
			size: (50, 50)
			// backgroundColor: Color? = nil
		)
	)

? Alert bubble view (localizable)

@State var showing = false
    
var body: some View {
	ZStack {
		// iOS 14 - Color for background 
		AlertBubbleView14(
			showing: $showing, 
			title: "Title", 
			subtitle: "Subtitle", 
			systemImage: "heart.fill", 
			background: .red
		)

		// iOS 15 - ShapeStyle for background
		AlertBubbleView(
			showing: $showing, 
			title: "Title", 
			subtitle: "Subtitle", 
			systemImage: "heart.fill", 
			background: .ultraThinMaterial
		)
	}
}

? Fully native emoji picker

@State var emoji = "?"
    
var body: some View {
	EmojiPickerView(emoji: $emoji)
}

? ImagePicker

// UIImage picked from user
@State var image: UIImage? = nil
// Presenting Image Picker
@State var showingPicker = false

var body: some View {
	VStack{
		// unwrap image and display
		if let image = image {
			Image(uiImage: image)
				.resizable()
		}
            
		// show image picker
		Button("Pick photo") {
			showingPicker.toggle()
		}
	}
	// image picker sheet
	.sheet(isPresented: $showingPicker) {
		ImagePickerView(image: $image)
	}
}

Shared

? Date to string with format

// Preset formats
Date().getString(with: .commaWithWeekday)
// Or custom formats
Date().getString(with: "MMMM yyyy")

? Number of day to another date

Date().numberOfDays(until: anotherDate)

? String to Date

"your date in string".toDate(with: "MM/dd/yyyy")
// Or use the Date.Formats
"your date in string".toDate(with: Date.Formats.slashes.rawValue)

? Check if string contains emoji

"emoji ?".hasEmoji()

? Print Error

error.printError(for: "Your label")
// Output
// Error occurred: Your label
// Localized error description
// Full error

? StoreKit localized price string

// iOS 15 Product
yourProduct.localizedPrice ?? "optional string"
// SKProduct
yourSKProduct.localizedPrice ?? "optional string"

? Reset userdefults

UserDefaults.standard.reset(for: ["key1", "key2"])

? Load local JSON Data

let data = Bundle.main.loadLocalJSON(with: "fileName")

? Request User notifications

UNUserNotificationCenter.requestPermission(for: [.alert, .badge, .sound]) {
	// Handle success
}

? Bring back user notification

.onAppear {
	// Triggers a notification 14 (your amount of days) days from the last time the user opened the app
	// With your given notification content
	UNUserNotificationCenter.bringBackUser(with: notificationContent, in: 14)
}

Onboarder

For detailed usage information on Onboarder, checkout the the Onboarder repo here.

Defaults

Default values for the following:

Font Sizes – Includes all predefined fonts in their CGFloat size

.font(.system(size: .body))

Opacities – Low, Medium, High

.opacity(.opacityLow)

URL – Default unwrapped url

URL(string: "Invalid URL") ?? .defaultURL

Date – Current values (day, month, year, hour, min, etc.)

Date.currentYear

Docs

Meta

Jem Alvarez – @official_JemAl[email protected]

Distributed under the MIT license. See LICENSE for more information.

JsHelper

GitHub

View Github