Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b93d2f0d2a | ||
|
|
2127942e5f | ||
|
|
fd1107d42e | ||
|
|
1487636084 | ||
|
|
4960d608b4 | ||
|
|
3b25741375 | ||
|
|
e3d7e76f14 | ||
|
|
2ae380ced9 | ||
|
|
43b76c064c | ||
|
|
242b6ae368 | ||
|
|
6ba3bf7309 | ||
|
|
d95b8e9225 | ||
|
|
bd9563a7d0 | ||
|
|
3551efffa5 |
@@ -0,0 +1 @@
|
||||
4.0
|
||||
@@ -1,7 +1,15 @@
|
||||
Changelog
|
||||
==========
|
||||
|
||||
### 1.0.7
|
||||
### 2.0.1
|
||||
|
||||
- Clean code and move loader position
|
||||
|
||||
### 2.0
|
||||
|
||||
- Swift 4 version
|
||||
|
||||
### 1.0.8
|
||||
|
||||
- Fix architecture
|
||||
- Add Carthage support
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
76EAA8661E93F2CC009A41DA /* ViewController.swift */,
|
||||
76EAA8891E93F66A009A41DA /* Sources */,
|
||||
76EAA8681E93F2CC009A41DA /* Main.storyboard */,
|
||||
76EAA86B1E93F2CC009A41DA /* Assets.xcassets */,
|
||||
76EAA86D1E93F2CC009A41DA /* LaunchScreen.storyboard */,
|
||||
76EAA86B1E93F2CC009A41DA /* Assets.xcassets */,
|
||||
76EAA8701E93F2CC009A41DA /* Info.plist */,
|
||||
);
|
||||
path = OpenSourceControllerDemo;
|
||||
@@ -120,12 +120,13 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 0830;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = OpenSourceController;
|
||||
TargetAttributes = {
|
||||
76EAA8601E93F2CC009A41DA = {
|
||||
CreatedOnToolsVersion = 8.3;
|
||||
DevelopmentTeam = 62PP362QNQ;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
@@ -210,7 +211,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@@ -218,7 +221,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -247,6 +254,7 @@
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -261,7 +269,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@@ -269,7 +279,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -290,6 +304,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
@@ -304,7 +319,8 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.fg.OpenSourceControllerDemo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -317,7 +333,8 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.fg.OpenSourceControllerDemo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildSystemType</key>
|
||||
<string>Latest</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildLocationStyle</key>
|
||||
<string>UseAppPreferences</string>
|
||||
<key>CustomBuildLocationType</key>
|
||||
<string>RelativeToDerivedData</string>
|
||||
<key>DerivedDataLocationStyle</key>
|
||||
<string>Default</string>
|
||||
<key>EnabledFullIndexStoreVisibility</key>
|
||||
<false/>
|
||||
<key>IssueFilterStyle</key>
|
||||
<string>ShowActiveSchemeOnly</string>
|
||||
<key>LiveSourceIssuesEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>OpenSourceControllerDemo.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
@@ -55,6 +56,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -1,89 +1,112 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 8-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 8.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 9-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 9.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 10-3.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 10-2.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 10-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "logo 10.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 4-1.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 4.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 5-1.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 5.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 6-1.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 6.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 7-2.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 7-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "logo 7.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "logo 7-3.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 287 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -24,7 +24,7 @@
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LI4-fC-2Ry">
|
||||
<rect key="frame" x="23" y="318" width="328" height="30"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<state key="normal" title="Show me"/>
|
||||
<connections>
|
||||
<action selector="showOpenSource:" destination="BYZ-38-t0r" eventType="touchUpInside" id="vmT-jj-Xvr"/>
|
||||
</connections>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -29,7 +29,7 @@ class ViewController: UIViewController {
|
||||
// Create controller
|
||||
let openSourceVC = OpenSourceController()
|
||||
|
||||
// Apply somre customisation if you want !
|
||||
// Apply some customisation if you want
|
||||
//self.controllerCustomUI(openSourceVC: openSourceVC)
|
||||
|
||||
// Init with LicenceFile object
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'OpenSourceController'
|
||||
s.version = '1.0.7'
|
||||
s.version = '2.0'
|
||||
s.summary = 'Display all the librarys licence used in your application. Enjoy !'
|
||||
s.description = 'Display a screen with all licence used in your apply can be painful to maintain. OpenSourceController was built to respond to this problem. OpenSourceController is a simple parser to display the licences which are used in your application.'
|
||||
s.homepage = 'https://github.com/terflogag/OpenSourceController'
|
||||
@@ -8,5 +8,5 @@ s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
s.author = { 'Florian Gabach' => 'contact@floriangabach.fr' }
|
||||
s.source = { :git => 'https://github.com/terflogag/OpenSourceController.git', :tag => s.version.to_s }
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.source_files = 'OpenSourceController/Sources/**/*'
|
||||
s.source_files = 'Sources/**/*'
|
||||
end
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0810;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = OpenSourceController;
|
||||
TargetAttributes = {
|
||||
52D6D97B1BEFF229002C0205 = {
|
||||
@@ -214,7 +214,7 @@
|
||||
};
|
||||
52D6D9851BEFF229002C0205 = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
LastSwiftMigration = 0800;
|
||||
LastSwiftMigration = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -294,14 +294,20 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -330,7 +336,7 @@
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -345,14 +351,20 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -373,7 +385,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -400,7 +412,7 @@
|
||||
PRODUCT_NAME = OpenSourceController;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -422,7 +434,7 @@
|
||||
PRODUCT_NAME = OpenSourceController;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildSystemType</key>
|
||||
<string>Latest</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildLocationStyle</key>
|
||||
<string>UseAppPreferences</string>
|
||||
<key>CustomBuildLocationType</key>
|
||||
<string>RelativeToDerivedData</string>
|
||||
<key>DerivedDataLocationStyle</key>
|
||||
<string>Default</string>
|
||||
<key>EnabledFullIndexStoreVisibility</key>
|
||||
<false/>
|
||||
<key>IssueFilterStyle</key>
|
||||
<string>ShowActiveSchemeOnly</string>
|
||||
<key>LiveSourceIssuesEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES">
|
||||
<Testables>
|
||||
@@ -56,6 +57,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES">
|
||||
<Testables>
|
||||
@@ -56,6 +57,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES">
|
||||
<Testables>
|
||||
@@ -56,6 +57,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES">
|
||||
<Testables>
|
||||
@@ -37,6 +38,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -37,22 +37,26 @@ Display a screen with all licences used in your application can be painful to ma
|
||||
|
||||
## Requirements
|
||||
|
||||
* Xcode 8
|
||||
* Xcode 9
|
||||
* iOS 9.0+ target deployment
|
||||
* Swift 3 project
|
||||
* Swift 3 or Swift 4 project
|
||||
|
||||
## Installation
|
||||
|
||||
- To integrate OpenSourceController into your Xcode project using [CocoaPods](http://cocoapods.org), specify it in your Podfile :
|
||||
|
||||
```ruby
|
||||
pod "OpenSourceController"
|
||||
pod "OpenSourceController", '~> 2.0'
|
||||
|
||||
pod "OpenSourceController", '~> 1.0.8' # Swift 3.1 version
|
||||
```
|
||||
|
||||
- To integrate OpenSourceController into your Xcode project using [Carthage](https://github.com/Carthage/Carthage), specify it in your Cartfile :
|
||||
|
||||
```ruby
|
||||
github "terflogag/OpenSourceController"
|
||||
github "floriangbh/OpenSourceController" ~> 2.0
|
||||
|
||||
github "floriangbh/OpenSourceController" ~> 1.0.8 # Swift 3.1 version
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -127,7 +131,7 @@ What about yours ? If your application also use this library, feel free to cont
|
||||
|
||||
## Author
|
||||
|
||||
Florian Gabach, contact@floriangabach.fr
|
||||
Florian Gabach, florian.gabach@gmail.com
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class OpenSourceController: NSObject {
|
||||
public class OpenSourceController: NSObject {
|
||||
|
||||
// Contains list of licence object
|
||||
open var licences: [LicenceFile]?
|
||||
|
||||
@@ -7,62 +7,80 @@
|
||||
import UIKit
|
||||
|
||||
class OpenSourceViewController: UITableViewController {
|
||||
|
||||
|
||||
// MARK: - Var
|
||||
|
||||
|
||||
/// Loading indicator
|
||||
fileprivate var indicator = UIActivityIndicatorView()
|
||||
|
||||
fileprivate lazy var indicator: UIActivityIndicatorView = {
|
||||
let indicator = UIActivityIndicatorView(frame:CGRect(x: 0,
|
||||
y: 0,
|
||||
width: 40,
|
||||
height: 40) )
|
||||
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
|
||||
indicator.hidesWhenStopped = true
|
||||
indicator.backgroundColor = UIColor.clear
|
||||
indicator.color = UIColor.black
|
||||
return indicator
|
||||
}()
|
||||
|
||||
/// TableViewCell identifier
|
||||
private let reuseIdentifier = "openSourceCell"
|
||||
|
||||
|
||||
/// Contains all licence object before downloaded
|
||||
internal var licences: [LicenceFile]?
|
||||
|
||||
|
||||
// Controller configuration for customization
|
||||
internal var config = OpenSourceControllerConfig()
|
||||
|
||||
|
||||
/// Contains all licences object after downloaded
|
||||
fileprivate var downloadedLicence: [LicenceFile]? {
|
||||
didSet {
|
||||
// Update UI
|
||||
DispatchQueue.main.async {
|
||||
self.stopLoading()
|
||||
self.tableView.reloadData()
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.stopLoading()
|
||||
self?.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Lifecyle
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Prepare tableview
|
||||
|
||||
// Prepare controller
|
||||
self.prepare()
|
||||
}
|
||||
|
||||
// MARK: - Prepare
|
||||
|
||||
/// Prepare controller
|
||||
fileprivate func prepare() {
|
||||
self.prepareTableView()
|
||||
|
||||
// Download licences
|
||||
self.prepareActivityIndicator()
|
||||
self.prepareCloseButton()
|
||||
self.prepareStyle()
|
||||
self.prepareLicences()
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
}
|
||||
|
||||
// MARK: - Prepare
|
||||
|
||||
|
||||
/// Download licences
|
||||
fileprivate func prepareLicences() {
|
||||
if let licences = self.licences {
|
||||
self.startLoading()
|
||||
LicenceDownloader.downloadLicences(licences: licences,
|
||||
config: self.config) { () in
|
||||
// Update licences
|
||||
self.downloadedLicence = self.licences
|
||||
}
|
||||
self.startLoading()
|
||||
|
||||
// Retrieve licence
|
||||
guard let licences = self.licences else {
|
||||
print("No licences found.")
|
||||
return
|
||||
}
|
||||
|
||||
// Download licence
|
||||
LicenceDownloader.downloadLicences(licences: licences,
|
||||
config: self.config) { () in
|
||||
// Update licences
|
||||
self.downloadedLicence = self.licences
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Init tableView dataSource, delegate, bar button & title
|
||||
fileprivate func prepareTableView() {
|
||||
// Common init
|
||||
@@ -74,65 +92,79 @@ class OpenSourceViewController: UITableViewController {
|
||||
self.tableView.dataSource = self
|
||||
self.tableView.delegate = self
|
||||
self.tableView.separatorStyle = .singleLine
|
||||
|
||||
// Apply background color from configuration if needed
|
||||
if let backgroundColor = self.config.uiConfig.backgroundColor {
|
||||
self.tableView.backgroundColor = backgroundColor
|
||||
}
|
||||
|
||||
// Navigation bar
|
||||
}
|
||||
|
||||
/// Prepare controller style
|
||||
fileprivate func prepareStyle() {
|
||||
// Apply navigation bar tint color if needed
|
||||
if let tintColor = self.config.uiConfig.barTintColor {
|
||||
self.navigationController?.navigationBar.barTintColor = tintColor
|
||||
}
|
||||
|
||||
// Applu navigation bar text color if needed
|
||||
if let textColor = self.config.uiConfig.titleColor {
|
||||
let attribut = [NSForegroundColorAttributeName: textColor]
|
||||
let attribut = [NSAttributedStringKey.foregroundColor: textColor]
|
||||
self.navigationController?.navigationBar.titleTextAttributes = attribut
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Prepare close button on navigation bar
|
||||
fileprivate func prepareCloseButton() {
|
||||
// Close button (on the right corner of navigation bar)
|
||||
let closeButton = UIBarButtonItem(barButtonSystemItem: .stop,
|
||||
target: self,
|
||||
action: #selector(self.closePicker))
|
||||
closeButton.tintColor = config.uiConfig.closeButtonColor ?? UIColor.black
|
||||
self.navigationItem.rightBarButtonItem = closeButton
|
||||
|
||||
// Loading indicator
|
||||
self.prepareActivityIndicator()
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Loading indicator
|
||||
|
||||
|
||||
/// Prepare UIActivityIndicatorView and display it at the center of the view
|
||||
fileprivate func prepareActivityIndicator() {
|
||||
self.indicator = UIActivityIndicatorView(frame:CGRect(x: 0, y: 0, width: 40, height: 40) )
|
||||
self.indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
|
||||
self.indicator.center = self.view.center
|
||||
// Add to view
|
||||
self.view.addSubview(indicator)
|
||||
|
||||
// Apply constraint
|
||||
self.indicator.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.indicator.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
||||
let topConstraint = self.navigationController?.navigationBar.frame.size.height ?? 0.0
|
||||
self.indicator.bottomAnchor.constraint(equalTo: view.topAnchor, constant: topConstraint).isActive=true
|
||||
}
|
||||
|
||||
|
||||
/// Start loading : start the loader animation
|
||||
fileprivate func startLoading() {
|
||||
self.indicator.startAnimating()
|
||||
self.indicator.backgroundColor = UIColor.clear
|
||||
self.indicator.color = UIColor.black
|
||||
self.indicator.isHidden = false
|
||||
|
||||
// Disable scroll
|
||||
self.tableView.isScrollEnabled = false
|
||||
}
|
||||
|
||||
|
||||
/// Stop loading : stop and hide the loader
|
||||
fileprivate func stopLoading() {
|
||||
self.indicator.hidesWhenStopped = true
|
||||
self.indicator.stopAnimating()
|
||||
self.indicator.isHidden = true
|
||||
|
||||
// Enable scroll
|
||||
self.tableView.isScrollEnabled = true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Table View Data Source
|
||||
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.downloadedLicence?.count ?? 0
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
var cell = tableView.dequeueReusableCell(withIdentifier: self.reuseIdentifier,
|
||||
for: indexPath) as? OpenSourceTableViewCell
|
||||
@@ -141,33 +173,33 @@ class OpenSourceViewController: UITableViewController {
|
||||
cell = OpenSourceTableViewCell(style: UITableViewCellStyle.default,
|
||||
reuseIdentifier: self.reuseIdentifier)
|
||||
}
|
||||
|
||||
|
||||
// Configure the cell with licence
|
||||
if let licence = self.downloadedLicence?.get(at: indexPath.row) {
|
||||
cell?.configure(licence: licence, config: self.config)
|
||||
}
|
||||
|
||||
|
||||
return cell!
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
// Automatic dimension
|
||||
return UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
|
||||
/// Handler for click on close button
|
||||
@objc fileprivate func closePicker() {
|
||||
self.dismissController()
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Navigation
|
||||
|
||||
|
||||
/// Dismiss the OpenSourceController
|
||||
func dismissController() {
|
||||
DispatchQueue.main.async {
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class LicenceFile: NSObject {
|
||||
public init(title: String, url: String) {
|
||||
self.title = title
|
||||
self.url = url
|
||||
self.detail = NSLocalizedString("Unable to load this licence.",
|
||||
self.detail = NSLocalizedString("Unable to load this licence file.",
|
||||
comment: "")
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class LicenceFile: NSObject {
|
||||
///
|
||||
/// - Parameter completion: end of download handler
|
||||
func downloadLicenceDetail(config: OpenSourceControllerConfig,
|
||||
completion: @escaping (Void) -> Void) {
|
||||
completion: @escaping () -> Void) {
|
||||
if let url = URL(string: self.url) {
|
||||
let task = URLSession.shared.dataTask(with: url) { (data, _, _) in
|
||||
if let data = data,
|
||||
|
||||
@@ -33,7 +33,7 @@ public struct OpenSourceControllerConfig {
|
||||
/// Will be applied to the navigation bar title
|
||||
public var title: String = "Tiers library"
|
||||
|
||||
// Verbose mode for print log when licence are downloaded
|
||||
/// Verbose mode for print log when licence are downloaded
|
||||
public var verbose: Bool = false
|
||||
|
||||
/// UI-specific configuration.
|
||||
|
||||
@@ -49,8 +49,8 @@ class OpenSourceTableViewCell: UITableViewCell {
|
||||
func configure(licence: LicenceFile, config: OpenSourceControllerConfig) {
|
||||
|
||||
// Build attributed text
|
||||
let libraryTitleAttribut = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize + 2)]
|
||||
let libraryLicenceAttribut = [NSFontAttributeName: UIFont.systemFont(ofSize: UIFont.systemFontSize)]
|
||||
let libraryTitleAttribut = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize + 2)]
|
||||
let libraryLicenceAttribut = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: UIFont.systemFontSize)]
|
||||
let libraryTitle = NSMutableAttributedString(string: licence.title ?? "",
|
||||
attributes: libraryTitleAttribut)
|
||||
libraryTitle.append(NSAttributedString(string: "\n\n"))
|
||||
|
||||