Skip to content

Commit b2841d1

Browse files
authored
Merge pull request #59 from nativeapptemplate/substrate-v2--cleanup-string-predicates
Cleanup: dead Date helper, swiftier String predicates, README env vars
2 parents f2a02ac + a542d27 commit b2841d1

22 files changed

Lines changed: 111 additions & 313 deletions

NativeAppTemplate.xcodeproj/project.pbxproj

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,103 +1268,6 @@
12681268
};
12691269
name = Release;
12701270
};
1271-
016595AF2824E3D800203F7F /* Beta configuration for PBXProject "NativeAppTemplate" */ = {
1272-
isa = XCBuildConfiguration;
1273-
buildSettings = {
1274-
ALWAYS_SEARCH_USER_PATHS = NO;
1275-
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
1276-
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
1277-
CLANG_ANALYZER_NONNULL = YES;
1278-
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1279-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
1280-
CLANG_CXX_LIBRARY = "libc++";
1281-
CLANG_ENABLE_MODULES = YES;
1282-
CLANG_ENABLE_OBJC_ARC = YES;
1283-
CLANG_ENABLE_OBJC_WEAK = YES;
1284-
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
1285-
CLANG_WARN_BOOL_CONVERSION = YES;
1286-
CLANG_WARN_COMMA = YES;
1287-
CLANG_WARN_CONSTANT_CONVERSION = YES;
1288-
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
1289-
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
1290-
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1291-
CLANG_WARN_EMPTY_BODY = YES;
1292-
CLANG_WARN_ENUM_CONVERSION = YES;
1293-
CLANG_WARN_INFINITE_RECURSION = YES;
1294-
CLANG_WARN_INT_CONVERSION = YES;
1295-
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
1296-
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
1297-
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
1298-
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
1299-
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
1300-
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
1301-
CLANG_WARN_STRICT_PROTOTYPES = YES;
1302-
CLANG_WARN_SUSPICIOUS_MOVE = YES;
1303-
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1304-
CLANG_WARN_UNREACHABLE_CODE = YES;
1305-
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
1306-
COPY_PHASE_STRIP = NO;
1307-
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1308-
DEVELOPMENT_TEAM = NNYDL5U3V3;
1309-
ENABLE_NS_ASSERTIONS = NO;
1310-
ENABLE_STRICT_OBJC_MSGSEND = YES;
1311-
ENABLE_USER_SCRIPT_SANDBOXING = YES;
1312-
GCC_C_LANGUAGE_STANDARD = gnu11;
1313-
GCC_NO_COMMON_BLOCKS = YES;
1314-
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
1315-
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
1316-
GCC_WARN_UNDECLARED_SELECTOR = YES;
1317-
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
1318-
GCC_WARN_UNUSED_FUNCTION = YES;
1319-
GCC_WARN_UNUSED_VARIABLE = YES;
1320-
IPHONEOS_DEPLOYMENT_TARGET = 17.2;
1321-
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1322-
MTL_ENABLE_DEBUG_INFO = NO;
1323-
MTL_FAST_MATH = YES;
1324-
SDKROOT = iphoneos;
1325-
STRING_CATALOG_GENERATE_SYMBOLS = YES;
1326-
SWIFT_COMPILATION_MODE = wholemodule;
1327-
SWIFT_EMIT_LOC_STRINGS = YES;
1328-
SWIFT_OPTIMIZATION_LEVEL = "-O";
1329-
SWIFT_STRICT_CONCURRENCY = complete;
1330-
SWIFT_VERSION = 6.0;
1331-
VALIDATE_PRODUCT = YES;
1332-
};
1333-
name = Beta;
1334-
};
1335-
016595B02824E3D800203F7F /* Beta configuration for PBXNativeTarget "NativeAppTemplate" */ = {
1336-
isa = XCBuildConfiguration;
1337-
buildSettings = {
1338-
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1339-
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
1340-
BUNDLE_ID_SUFFIX = .beta;
1341-
CODE_SIGN_ENTITLEMENTS = "";
1342-
CODE_SIGN_STYLE = Automatic;
1343-
CURRENT_PROJECT_VERSION = 9;
1344-
DEVELOPMENT_ASSET_PATHS = "\"NativeAppTemplate/Preview Content\"";
1345-
ENABLE_PREVIEWS = YES;
1346-
ENABLE_USER_SCRIPT_SANDBOXING = NO;
1347-
INFOPLIST_FILE = NativeAppTemplate/Info.plist;
1348-
INFOPLIST_KEY_CFBundleDisplayName = "NativeAppTemplate Free";
1349-
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business";
1350-
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
1351-
LD_RUNPATH_SEARCH_PATHS = (
1352-
"$(inherited)",
1353-
"@executable_path/Frameworks",
1354-
);
1355-
MARKETING_VERSION = 3.1.1;
1356-
PRODUCT_BUNDLE_IDENTIFIER = "com.nativeapptemplate.NativeAppTemplateFree.ios${SAMPLE_CODE_DISAMBIGUATOR}$(BUNDLE_ID_SUFFIX)";
1357-
PRODUCT_NAME = NativeAppTemplate;
1358-
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
1359-
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
1360-
SUPPORTS_MACCATALYST = NO;
1361-
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
1362-
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
1363-
SWIFT_VERSION = 6.0;
1364-
TARGETED_DEVICE_FAMILY = "1,2";
1365-
};
1366-
name = Beta;
1367-
};
13681271
01D19B4A2D4DE33500BDEAB7 /* Debug configuration for PBXNativeTarget "NativeAppTemplateTests" */ = {
13691272
isa = XCBuildConfiguration;
13701273
buildSettings = {
@@ -1406,26 +1309,6 @@
14061309
};
14071310
name = Release;
14081311
};
1409-
01D19B4C2D4DE33500BDEAB7 /* Beta configuration for PBXNativeTarget "NativeAppTemplateTests" */ = {
1410-
isa = XCBuildConfiguration;
1411-
buildSettings = {
1412-
BUNDLE_LOADER = "$(TEST_HOST)";
1413-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
1414-
CODE_SIGN_STYLE = Automatic;
1415-
CURRENT_PROJECT_VERSION = 1;
1416-
GCC_C_LANGUAGE_STANDARD = gnu17;
1417-
GENERATE_INFOPLIST_FILE = YES;
1418-
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
1419-
MARKETING_VERSION = 1.0;
1420-
PRODUCT_BUNDLE_IDENTIFIER = com.nativeapptemplate.NativeAppTemplateTests;
1421-
PRODUCT_NAME = "$(TARGET_NAME)";
1422-
SWIFT_EMIT_LOC_STRINGS = NO;
1423-
SWIFT_VERSION = 5.0;
1424-
TARGETED_DEVICE_FAMILY = "1,2";
1425-
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NativeAppTemplate.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NativeAppTemplate";
1426-
};
1427-
name = Beta;
1428-
};
14291312
/* End XCBuildConfiguration section */
14301313

14311314
/* Begin XCConfigurationList section */
@@ -1434,7 +1317,6 @@
14341317
buildConfigurations = (
14351318
011F6E10259EF16600BED22E /* Debug configuration for PBXProject "NativeAppTemplate" */,
14361319
011F6E11259EF16600BED22E /* Release configuration for PBXProject "NativeAppTemplate" */,
1437-
016595AF2824E3D800203F7F /* Beta configuration for PBXProject "NativeAppTemplate" */,
14381320
);
14391321
defaultConfigurationName = Release;
14401322
};
@@ -1443,7 +1325,6 @@
14431325
buildConfigurations = (
14441326
011F6E13259EF16600BED22E /* Debug configuration for PBXNativeTarget "NativeAppTemplate" */,
14451327
011F6E14259EF16600BED22E /* Release configuration for PBXNativeTarget "NativeAppTemplate" */,
1446-
016595B02824E3D800203F7F /* Beta configuration for PBXNativeTarget "NativeAppTemplate" */,
14471328
);
14481329
defaultConfigurationName = Release;
14491330
};
@@ -1452,7 +1333,6 @@
14521333
buildConfigurations = (
14531334
01D19B4A2D4DE33500BDEAB7 /* Debug configuration for PBXNativeTarget "NativeAppTemplateTests" */,
14541335
01D19B4B2D4DE33500BDEAB7 /* Release configuration for PBXNativeTarget "NativeAppTemplateTests" */,
1455-
01D19B4C2D4DE33500BDEAB7 /* Beta configuration for PBXNativeTarget "NativeAppTemplateTests" */,
14561336
);
14571337
defaultConfigurationName = Release;
14581338
};

NativeAppTemplate/Extensions/Date+Extensions.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,4 @@ extension Date {
2424
var cardDateTimeString: String {
2525
"\(cardDateString) \(cardTimeString)"
2626
}
27-
28-
var cardTimeAgoInWordsDateString: String {
29-
let formatter = DateFormatter.timeAgoInWordsDateFormatter
30-
return formatter.string(from: self)
31-
}
3227
}

NativeAppTemplate/Extensions/DateFormatter+Extensions.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,6 @@ extension DateFormatter {
3333

3434
static let cardTimeFormatter: DateFormatter = .formatter(for: "HH:mm")
3535

36-
static let timeAgoInWordsDateFormatter: DateFormatter = {
37-
let dateFormatter = DateFormatter()
38-
dateFormatter.dateStyle = .short
39-
dateFormatter.timeStyle = .medium
40-
dateFormatter.doesRelativeDateFormatting = true
41-
return dateFormatter
42-
}()
43-
4436
static func formatter(for dateString: String) -> DateFormatter {
4537
let dateFormatter = DateFormatter()
4638
dateFormatter.dateFormat = dateString

NativeAppTemplate/Extensions/String+Extensions.swift

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,15 @@
33
// NativeAppTemplate
44
//
55

6-
import UIKit
6+
import Foundation
77

88
extension String {
9-
/// Generates a `UIImage` instance from this string using a specified
10-
/// attributes and size.
11-
///
12-
/// - Parameters:
13-
/// - attributes: to draw this string with. Default is `nil`.
14-
/// - size: of the image to return.
15-
/// - Returns: a `UIImage` instance from this string using a specified
16-
/// attributes and size, or `nil` if the operation fails.
17-
func image(withAttributes attributes: [NSAttributedString.Key: Any]? = nil, size: CGSize? = nil) -> UIImage? {
18-
let size = size ?? (self as NSString).size(withAttributes: attributes)
19-
return UIGraphicsImageRenderer(size: size).image { _ in
20-
(self as NSString).draw(
21-
in: CGRect(origin: .zero, size: size),
22-
withAttributes: attributes
23-
)
24-
}
9+
var isBlank: Bool {
10+
trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
2511
}
2612

27-
func isAlphanumeric() -> Bool {
28-
rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) == nil && !isEmpty
29-
}
30-
31-
func isAlphanumeric(ignoreDiacritics: Bool = false) -> Bool {
32-
if ignoreDiacritics {
33-
range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil && !isEmpty
34-
} else {
35-
isAlphanumeric()
36-
}
13+
var isValidEmail: Bool {
14+
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
15+
return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
3716
}
3817
}

NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ final class ForgotPasswordViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) {
28+
if email.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

3636
return false
3737
}
3838

3939
var isEmailBlank: Bool {
40-
Utility.isBlank(email)
40+
email.isBlank
4141
}
4242

4343
var isEmailInvalid: Bool {
44-
!Utility.isBlank(email) && !Utility.validateEmail(email)
44+
!email.isBlank && !email.isValidEmail
4545
}
4646

4747
func sendMeResetPasswordInstructionsTapped() {

NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ final class ResendConfirmationInstructionsViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) {
28+
if email.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

3636
return false
3737
}
3838

3939
var isEmailBlank: Bool {
40-
Utility.isBlank(email)
40+
email.isBlank
4141
}
4242

4343
var isEmailInvalid: Bool {
44-
!Utility.isBlank(email) && !Utility.validateEmail(email)
44+
!email.isBlank && !email.isValidEmail
4545
}
4646

4747
func sendMeConfirmationInstructionsTapped() {

NativeAppTemplate/UI/App Root/SignInEmailAndPasswordViewModel.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ final class SignInEmailAndPasswordViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) || Utility.isBlank(password) {
28+
if email.isBlank || password.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

@@ -41,23 +41,23 @@ final class SignInEmailAndPasswordViewModel {
4141
}
4242

4343
var hasInvalidDataPassword: Bool {
44-
if Utility.isBlank(password) {
44+
if password.isBlank {
4545
return true
4646
}
4747

4848
return false
4949
}
5050

5151
var isEmailBlank: Bool {
52-
Utility.isBlank(email)
52+
email.isBlank
5353
}
5454

5555
var isEmailInvalid: Bool {
56-
Utility.isBlank(email) || !Utility.validateEmail(email)
56+
email.isBlank || !email.isValidEmail
5757
}
5858

5959
var isPasswordBlank: Bool {
60-
Utility.isBlank(password)
60+
password.isBlank
6161
}
6262

6363
func signIn() {

NativeAppTemplate/UI/App Root/SignUpViewModel.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class SignUpViewModel {
3131
}
3232

3333
var hasInvalidData: Bool {
34-
if Utility.isBlank(name) {
34+
if name.isBlank {
3535
return true
3636
}
3737

@@ -47,19 +47,19 @@ final class SignUpViewModel {
4747
}
4848

4949
var hasInvalidDataEmail: Bool {
50-
if Utility.isBlank(email) {
50+
if email.isBlank {
5151
return true
5252
}
5353

54-
if !Utility.validateEmail(email) {
54+
if !email.isValidEmail {
5555
return true
5656
}
5757

5858
return false
5959
}
6060

6161
var hasInvalidDataPassword: Bool {
62-
if Utility.isBlank(password) {
62+
if password.isBlank {
6363
return true
6464
}
6565

@@ -71,15 +71,15 @@ final class SignUpViewModel {
7171
}
7272

7373
var isNameBlank: Bool {
74-
Utility.isBlank(name)
74+
name.isBlank
7575
}
7676

7777
var isEmailBlank: Bool {
78-
Utility.isBlank(email)
78+
email.isBlank
7979
}
8080

8181
var isPasswordBlank: Bool {
82-
Utility.isBlank(password)
82+
password.isBlank
8383
}
8484

8585
func createShopkeeper() {

NativeAppTemplate/UI/Settings/PasswordEditView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private extension PasswordEditView {
5252
Text(Strings.weNeedYourCurrentPassword)
5353
.font(.uiFootnote)
5454
Text(Strings.currentPasswordIsRequired)
55-
.foregroundStyle(Utility.isBlank(viewModel.currentPassword) ? .validationError : .clear)
55+
.foregroundStyle(viewModel.currentPassword.isBlank ? .validationError : .clear)
5656
.font(.uiFootnote)
5757
}
5858
}
@@ -68,7 +68,7 @@ private extension PasswordEditView {
6868
Text("\(viewModel.minimumPasswordLength) characters minimum.")
6969
.font(.uiFootnote)
7070

71-
if Utility.isBlank(viewModel.password) {
71+
if viewModel.password.isBlank {
7272
Text(Strings.newPasswordIsRequired)
7373
.foregroundStyle(.validationError)
7474
.font(.uiFootnote)
@@ -89,7 +89,7 @@ private extension PasswordEditView {
8989
} footer: {
9090
Text(Strings.confirmNewPasswordIsRequired)
9191
.font(.uiFootnote)
92-
.foregroundStyle(Utility.isBlank(viewModel.passwordConfirmation) ? .validationError : .clear)
92+
.foregroundStyle(viewModel.passwordConfirmation.isBlank ? .validationError : .clear)
9393
}
9494
}
9595
.navigationTitle(Strings.updatePassword)

0 commit comments

Comments
 (0)