make ipa exporting easier
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
/.nvim
|
/.nvim
|
||||||
.DS_Store
|
.DS_Store
|
||||||
buildServer.json
|
buildServer.json
|
||||||
|
.swiftlint.yml
|
||||||
|
|||||||
13
ExportOptions.plist
Normal file
13
ExportOptions.plist
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?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>uploadBitcode</key>
|
||||||
|
<false/>
|
||||||
|
<key>uploadSymbols</key>
|
||||||
|
<true/>
|
||||||
|
<key>compileBitcode</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -5,11 +5,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func application(_ application: UIApplication,
|
func application(
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
_ application: UIApplication,
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||||||
window?.rootViewController = ViewController()
|
) -> Bool {
|
||||||
window?.makeKeyAndVisible()
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
return true
|
window?.rootViewController = ViewController()
|
||||||
}
|
window?.makeKeyAndVisible()
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ enum PageTurnMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||||
|
|
||||||
var imageView = UIImageView()
|
var imageView = UIImageView()
|
||||||
var images: [UIImage] = []
|
var images: [UIImage] = []
|
||||||
var page = 0
|
var page = 0
|
||||||
@@ -23,8 +22,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
var topTap: UITapGestureRecognizer!
|
var topTap: UITapGestureRecognizer!
|
||||||
|
|
||||||
let topBarView = UIView()
|
let topBarView = UIView()
|
||||||
let topBarLabel = UILabel()
|
|
||||||
var topBarHeightConstraint: NSLayoutConstraint!
|
|
||||||
|
|
||||||
let pageTurnDropdownView = UIView()
|
let pageTurnDropdownView = UIView()
|
||||||
let pageTurnDropdownButton = UIButton()
|
let pageTurnDropdownButton = UIButton()
|
||||||
@@ -41,6 +38,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
|
createTestFile()
|
||||||
setupImageView()
|
setupImageView()
|
||||||
setupGestures()
|
setupGestures()
|
||||||
setupTopBar()
|
setupTopBar()
|
||||||
@@ -111,24 +109,11 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
topBarView.isHidden = true
|
topBarView.isHidden = true
|
||||||
view.addSubview(topBarView)
|
view.addSubview(topBarView)
|
||||||
|
|
||||||
topBarHeightConstraint = topBarView.heightAnchor.constraint(equalToConstant: 0)
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
topBarView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
|
topBarView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
|
||||||
topBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
topBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
topBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
topBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
topBarHeightConstraint,
|
topBarView.heightAnchor.constraint(equalToConstant: 64),
|
||||||
])
|
|
||||||
|
|
||||||
topBarLabel.text = "Menu"
|
|
||||||
topBarLabel.textColor = .white
|
|
||||||
topBarLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
topBarLabel.isHidden = true
|
|
||||||
topBarView.addSubview(topBarLabel)
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
topBarLabel.centerXAnchor.constraint(equalTo: topBarView.centerXAnchor),
|
|
||||||
topBarLabel.centerYAnchor.constraint(equalTo: topBarView.centerYAnchor),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
setupBackgroundColorDropdown()
|
setupBackgroundColorDropdown()
|
||||||
@@ -143,7 +128,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
topBarView.addSubview(backgroundColorDropdownButton)
|
topBarView.addSubview(backgroundColorDropdownButton)
|
||||||
|
|
||||||
backgroundColorDropdownButton.addTarget(
|
backgroundColorDropdownButton.addTarget(
|
||||||
self, action: #selector(toggleBackgroundColorDropdown), for: .touchDown)
|
self, action: #selector(toggleBackgroundColorDropdown), for: .touchDown
|
||||||
|
)
|
||||||
|
|
||||||
backgroundColorDropdownView.backgroundColor = UIColor.darkGray
|
backgroundColorDropdownView.backgroundColor = UIColor.darkGray
|
||||||
backgroundColorDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
backgroundColorDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@@ -169,13 +155,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
button.backgroundColor = .clear
|
button.backgroundColor = .clear
|
||||||
button.translatesAutoresizingMaskIntoConstraints = false
|
button.translatesAutoresizingMaskIntoConstraints = false
|
||||||
button.addTarget(
|
button.addTarget(
|
||||||
self, action: #selector(handleBackgroundColorOption), for: .touchDown)
|
self, action: #selector(handleBackgroundColorOption), for: .touchDown
|
||||||
|
)
|
||||||
stackView.addArrangedSubview(button)
|
stackView.addArrangedSubview(button)
|
||||||
}
|
}
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
backgroundColorDropdownButton.leadingAnchor.constraint(
|
backgroundColorDropdownButton.leadingAnchor.constraint(
|
||||||
equalTo: topBarView.leadingAnchor, constant: 32),
|
equalTo: topBarView.leadingAnchor, constant: 32
|
||||||
|
),
|
||||||
backgroundColorDropdownButton.centerYAnchor.constraint(
|
backgroundColorDropdownButton.centerYAnchor.constraint(
|
||||||
equalTo: topBarView.centerYAnchor),
|
equalTo: topBarView.centerYAnchor),
|
||||||
backgroundColorDropdownButton.topAnchor.constraint(
|
backgroundColorDropdownButton.topAnchor.constraint(
|
||||||
@@ -197,7 +185,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
stackView.trailingAnchor.constraint(
|
stackView.trailingAnchor.constraint(
|
||||||
equalTo: backgroundColorDropdownView.trailingAnchor),
|
equalTo: backgroundColorDropdownView.trailingAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupPageTurnDropdown() {
|
func setupPageTurnDropdown() {
|
||||||
@@ -208,7 +195,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
topBarView.addSubview(pageTurnDropdownButton)
|
topBarView.addSubview(pageTurnDropdownButton)
|
||||||
|
|
||||||
pageTurnDropdownButton.addTarget(
|
pageTurnDropdownButton.addTarget(
|
||||||
self, action: #selector(togglePageTurnDropdown), for: .touchDown)
|
self, action: #selector(togglePageTurnDropdown), for: .touchDown
|
||||||
|
)
|
||||||
|
|
||||||
pageTurnDropdownView.backgroundColor = UIColor.darkGray
|
pageTurnDropdownView.backgroundColor = UIColor.darkGray
|
||||||
pageTurnDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
pageTurnDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@@ -234,13 +222,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
button.translatesAutoresizingMaskIntoConstraints = false
|
button.translatesAutoresizingMaskIntoConstraints = false
|
||||||
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
|
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
|
||||||
button.addTarget(
|
button.addTarget(
|
||||||
self, action: #selector(handlePageTurnOption), for: .touchDown)
|
self, action: #selector(handlePageTurnOption), for: .touchDown
|
||||||
|
)
|
||||||
stackView.addArrangedSubview(button)
|
stackView.addArrangedSubview(button)
|
||||||
}
|
}
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
pageTurnDropdownButton.trailingAnchor.constraint(
|
pageTurnDropdownButton.leadingAnchor.constraint(
|
||||||
equalTo: topBarView.trailingAnchor, constant: -32),
|
equalTo: backgroundColorDropdownButton.trailingAnchor, constant: 32
|
||||||
|
),
|
||||||
pageTurnDropdownButton.centerYAnchor.constraint(
|
pageTurnDropdownButton.centerYAnchor.constraint(
|
||||||
equalTo: topBarView.centerYAnchor),
|
equalTo: topBarView.centerYAnchor),
|
||||||
pageTurnDropdownButton.topAnchor.constraint(
|
pageTurnDropdownButton.topAnchor.constraint(
|
||||||
@@ -262,7 +252,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
stackView.trailingAnchor.constraint(
|
stackView.trailingAnchor.constraint(
|
||||||
equalTo: pageTurnDropdownView.trailingAnchor),
|
equalTo: pageTurnDropdownView.trailingAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func handlePageTurnOption(_ sender: UIButton) {
|
@objc func handlePageTurnOption(_ sender: UIButton) {
|
||||||
@@ -314,9 +303,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
func toggleTopBar() {
|
func toggleTopBar() {
|
||||||
topBarView.isHidden.toggle()
|
topBarView.isHidden.toggle()
|
||||||
|
|
||||||
topBarHeightConstraint.constant = !topBarView.isHidden ? 64 : 0 // You can adjust height
|
|
||||||
topBarLabel.isHidden = topBarView.isHidden
|
|
||||||
|
|
||||||
pageTurnDropdownButton.isHidden = topBarView.isHidden
|
pageTurnDropdownButton.isHidden = topBarView.isHidden
|
||||||
backgroundColorDropdownButton.isHidden = topBarView.isHidden
|
backgroundColorDropdownButton.isHidden = topBarView.isHidden
|
||||||
|
|
||||||
@@ -391,49 +377,59 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
imageView.image = images[page]
|
imageView.image = images[page]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getImages() -> [UIImage] {
|
func getImages() -> [UIImage] {
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
let supportedExtensions = ["png", "jpg", "jpeg"]
|
let supportedExtensions = ["png", "jpg", "jpeg"]
|
||||||
|
|
||||||
guard
|
guard
|
||||||
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
|
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
|
||||||
else {
|
else {
|
||||||
print("Documents directory not found.")
|
print("Documents directory not found.")
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
let contents = try fileManager.contentsOfDirectory(
|
|
||||||
at: documentsURL, includingPropertiesForKeys: nil)
|
|
||||||
|
|
||||||
var images: [UIImage] = []
|
|
||||||
|
|
||||||
for file in contents {
|
|
||||||
if supportedExtensions.contains(file.pathExtension.lowercased()) {
|
|
||||||
print("Loading image: \(file.lastPathComponent)")
|
|
||||||
if let image = UIImage(contentsOfFile: file.path) {
|
|
||||||
images.append(image)
|
|
||||||
} else {
|
|
||||||
print("Failed to load image.")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print("No image files found in Documents directory.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return images
|
|
||||||
} catch {
|
|
||||||
print("Error reading contents of Documents directory: \(error)")
|
|
||||||
}
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
func createTestFile() {
|
|
||||||
if let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
do {
|
||||||
.first
|
let contents = try fileManager.contentsOfDirectory(
|
||||||
{
|
at: documentsURL, includingPropertiesForKeys: nil
|
||||||
let fileURL = documentsURL.appendingPathComponent("dummy.txt")
|
)
|
||||||
let data = ".".data(using: .utf8)!
|
|
||||||
try? data.write(to: fileURL)
|
var images: [UIImage] = []
|
||||||
|
|
||||||
|
for file in contents {
|
||||||
|
if supportedExtensions.contains(file.pathExtension.lowercased()) {
|
||||||
|
print("Loading image: \(file.lastPathComponent)")
|
||||||
|
if let image = UIImage(contentsOfFile: file.path) {
|
||||||
|
images.append(image)
|
||||||
|
} else {
|
||||||
|
print("Failed to load image.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("No image files found in Documents directory.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return images
|
||||||
|
} catch {
|
||||||
|
print("Error reading contents of Documents directory: \(error)")
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestFile() {
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
if let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
|
||||||
|
.first
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
let contents = try fileManager.contentsOfDirectory(atPath: documentsURL.path)
|
||||||
|
if contents.isEmpty {
|
||||||
|
let fileURL = documentsURL.appendingPathComponent("dummy.txt")
|
||||||
|
let data = Data(".".utf8)
|
||||||
|
try? data.write(to: fileURL)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print("Error reading directory contents: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
archive.sh
Executable file
12
archive.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
xcodebuild archive \
|
||||||
|
-scheme ImageViewer \
|
||||||
|
-configuration Release \
|
||||||
|
-archivePath ./build/ImageViewer.xcarchive \
|
||||||
|
-destination 'generic/platform=iOS'
|
||||||
|
|
||||||
|
xcodebuild -exportArchive \
|
||||||
|
-archivePath ./build/ImageViewer.xcarchive \
|
||||||
|
-exportOptionsPlist ./ExportOptions.plist \
|
||||||
|
-exportPath ./build/ipa
|
||||||
9
run.sh
9
run.sh
@@ -3,20 +3,19 @@
|
|||||||
APP_NAME='ImageViewer'
|
APP_NAME='ImageViewer'
|
||||||
SIM_DEVICE='iPad Air 11-inch (M3)'
|
SIM_DEVICE='iPad Air 11-inch (M3)'
|
||||||
SCHEME='ImageViewer'
|
SCHEME='ImageViewer'
|
||||||
DERIVED_DATA="./build"
|
|
||||||
SIMULATOR='iOS Simulator'
|
SIMULATOR='iOS Simulator'
|
||||||
COMPANY='ImageViewer'
|
COMPANY='ImageViewer'
|
||||||
|
|
||||||
|
[ -z "$BUILD_TYPE" ] && BUILD_TYPE=Debug
|
||||||
|
DERIVED_DATA="./build"
|
||||||
|
|
||||||
sudo bash -c "echo '127.0.0.1 developerservices2.apple.com' >>/etc/hosts"
|
sudo bash -c "echo '127.0.0.1 developerservices2.apple.com' >>/etc/hosts"
|
||||||
|
|
||||||
# Boot and launch simulator
|
|
||||||
xcrun simctl boot "$SIM_DEVICE"
|
xcrun simctl boot "$SIM_DEVICE"
|
||||||
open -a Simulator
|
open -a Simulator
|
||||||
|
|
||||||
# Build app
|
xcodebuild -scheme "$SCHEME" -configuration "$BUILD_TYPE" -derivedDataPath "$DERIVED_DATA/$BUILD_TYPE" -destination "platform=$SIMULATOR,name=$SIM_DEVICE"
|
||||||
xcodebuild -scheme "$SCHEME" -derivedDataPath "$DERIVED_DATA" -destination "platform=$SIMULATOR,name=$SIM_DEVICE"
|
|
||||||
|
|
||||||
# Install and launch
|
|
||||||
APP_PATH="$DERIVED_DATA/Build/Products/Debug-iphonesimulator/$APP_NAME.app"
|
APP_PATH="$DERIVED_DATA/Build/Products/Debug-iphonesimulator/$APP_NAME.app"
|
||||||
xcrun simctl install booted "$APP_PATH"
|
xcrun simctl install booted "$APP_PATH"
|
||||||
xcrun simctl spawn booted log stream --predicate 'process == "ImageViewer"' --style syslog &
|
xcrun simctl spawn booted log stream --predicate 'process == "ImageViewer"' --style syslog &
|
||||||
|
|||||||
Reference in New Issue
Block a user