I have a SwiftUI view with a button. I want to open a window sheet from a storyboard. Showing a window sheet isn't a problem. It's just that the application no longer has a menu bar. As soon as I created a storyboard and a view controller (NSViewController), the application stopped showing up properly. Now, if I try to debug it (Command + R), the window won't appear. So I have to click on the Live Preview button on the Canvas. If I do, I can click on the Bring Forward button. Finally, if I click on it, the application window always appears at the bottom-left corner of the desktop without the menu bar. So what's the issue?
Anyway, the following is my code.
// SwiftUI View //
import SwiftUI
struct ContentView: View {
		@State private var sheetPresented = false
		@State private var selectionIndex = 3
		
		var body: some View {
				ZStack {
						VStack {
								Button(action: {
										sheetPresented = true
								}) {
										Text("Show me a sheet")
								}
								.sheet(isPresented: $sheetPresented) {
										SheetViewControllerRepresentation(message: String(selectionIndex))
								}
						}
				}.frame(minWidth: 360, idealWidth: 360, maxWidth: 360, minHeight: 240, idealHeight: 240, maxHeight: 240, alignment: .center)
		}
}
// View controller //
import Cocoa
import SwiftUI
class SheetViewController: NSViewController {
		// MARK: -
		var message = String()
		
		
		// MARK: - IBOutlet
		@IBOutlet weak var messageLabel: NSTextField!
		
		
		// MARK: - Life cycle
		override func viewDidLoad() {
				super.viewDidLoad()
				// Do view setup here.
		}
		
		override func viewWillAppear() {
				super.viewWillAppear()
				
				messageLabel.stringValue = message
		}
		
		override func viewDidAppear() {
				super.viewDidAppear()
				
				view.setFrameSize(CGSize(width: 320, height: 220))
		}
}
struct SheetViewControllerRepresentation: NSViewControllerRepresentable {
		var message = String()
		
		func makeNSViewController(context: NSViewControllerRepresentableContext<SheetViewControllerRepresentation>) -> SheetViewController {
				let mainStoryboard = NSStoryboard(name: "Main", bundle: nil)
				let sheetViewController = mainStoryboard.instantiateController(withIdentifier: "SheetView") as! SheetViewController
				sheetViewController.message = self.message
				return sheetViewController
		}
		
		func updateNSViewController(_ nsViewController: SheetViewController, context: NSViewControllerRepresentableContext<SheetViewControllerRepresentation>) {
		}
}
Thank you.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Let me suppose that I have an Xcode project that uses the following Cocoapods.
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
And let me also suppose that the minimum deployment target for my Xcode project is 11.0. In this case, do I set the Cocoapod platform to 11.0 like
platform :ios, '11.0'
target 'MyProject' do
	use_frameworks!
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
end
Or do I use the latest versions of Cocoapods like
platform :ios, '14.2'
target 'MyProject' do
	use_frameworks!
	pod 'Firebase/Auth'
	pod 'GoogleSignIn'
end
?
Thanks.
When you develop an iOS app for some company, say Company A, under whose name should you sign up a developer account so that you can code-sign the app and send it to the iTunes Connect server? Is it you or Company A? I am thinking that I can sign up a new account to submit an app as long as I give the copyright to Company A. My concern is that there was a new rule like Spamming that took effect several years ago. I guess some guys were using the same package and only changed superficial aspects to submit a ton of similar apps. Thanks.
p.s. It's not an in-house app under an enterprise account that I'm talking about. The app will be submitted to the App Store.
I'm playing with @EnvironmentObject to see how it works in SwiftUI. I have the main view (ContentView) where it says the user has not logged in yet. By letting the user tap a link, I want to make it such that they can log in by tapping a button.
class LoginMe: ObservableObject {
@Published var loggedIn = false
}
struct ContentView: View {
@StateObject var loginMe = LoginMe()
var body: some View {
if loginMe.loggedIn {
Text("Yes, I'm logged in")
} else {
NavigationView {
VStack {
Text("No, not logged in yet")
.padding(.vertical)
NavigationLink(destination: LoginView()) {
Text("Tap to log in")
}
}
.navigationBarTitle("User")
}
.environmentObject(loginMe)
}
}
}
struct LoginView: View {
@EnvironmentObject var loginMe: LoginMe
var body: some View {
/*
Toggle(isOn: $loginMe.loggedIn) {
Text("Log in")
}.padding(.horizontal)
*/
Button("Login") {
loginMe.loggedIn.toggle()
}
}
}
So far, when the user taps a button in the LoginView view, the screen goes back to ContentView and the navigation simply disappears. How can I change my code so that the status will change back and forth in in the LoginView view by tapping a button and then so that they can return to ContentView the navigation return button? I think the problem is that I need to use @State var in ContentView and @Binding var in LoginView. Things are kind of confusing. Muchos thankos.
import SwiftUI
struct ContentView: View {
@State var numbers = [2021, 9, 30]
var body: some View {
//let firstLocalYear = 2021
let firstLocalMonth = 9
let firstLocalDay = 24
let firstLastDay = 30
NavigationView {
List {
Section(header: Text("Current month")) {
ForEach(firstLocalDay ..< firstLastDay) { i in
HStack {
Text("\(firstLocalMonth)-\(i + 1)")
Spacer()
NavigationLink(
destination: TimeView(numbers: $numbers),
label: {
Text("")
})
}
}
}
}
}
}
}
struct TimeView: View {
@Binding var numbers: [Int]
var body: some View {
HStack {
Text(String(numbers[0]))
Text(String(numbers[1]))
Text(String(numbers[2]))
}
}
}
I have the lines of code above to list some rows of text. For now, numbers is a state variable that is pre-determined. This state variable is passed on to TimeView. Actually, I want to change this array depending on which row the user selects like
numbers = [firstLocalYear, firstLocalMonth, i]
where i comes from the ForEach thing. How can I change this array? Muchos thankos.
Hello,
I'm trying to work out a simple example to fill table view data with Combine. The following is what I have.
import Foundation
struct MyModel: Decodable {
let id: String
let type: String
}
import UIKit
import Combine
class APIClient: NSObject {
var cancellable: AnyCancellable?
let sharedSession = URLSession.shared
func fetchData(urlStr: String, completion: @escaping ([MyModel]?) -> Void) {
guard let url = URL(string: urlStr) else {
return
}
let publisher = sharedSession.dataTaskPublisher(for: url)
cancellable = publisher.sink(receiveCompletion: { (completion) in
switch completion {
case .failure(let error):
print(error)
case .finished:
print("Success")
}
}, receiveValue: { (result) in
let decoder = JSONDecoder()
do {
let post = try decoder.decode([MyModel].self, from: result.data)
completion(post)
} catch let error as NSError {
print("\(error)")
completion(nil)
}
})
}
}
import Foundation
class ViewModel: NSObject {
@IBOutlet var apiClient: APIClient!
var dataModels = [MyModel]()
func getGitData(completion: @escaping () -> Void) {
let urlStr = "https://api.github.com/repos/ReactiveX/RxSwift/events"
apiClient.fetchData(urlStr: urlStr) { (models) in
if let myModels = models {
self.dataModels = myModels.map { $0 }
}
completion()
}
}
}
import UIKit
import Combine
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Variables
var cancellable: AnyCancellable?
@IBOutlet var viewModel: ViewModel!
@Published var models = [MyModel]()
// MARK: - IBOutlet
@IBOutlet weak var tableView: UITableView!
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
viewModel.getGitData {
self.models = self.viewModel.dataModels
}
cancellable = $models.sink(receiveValue: { (result) in
DispatchQueue.main.async {
[weak self] in
guard let strongSelf = self else { return }
strongSelf.tableView.reloadData()
}
})
}
// MARK: - TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let dataModel = models[indexPath.row]
cell?.textLabel?.text = dataModel.id
cell?.detailTextLabel?.text = dataModel.type
return cell!
}
}
I'm not quite comfortable with the lines of code under my view controller (ViewController) in using Combine. How can I make them better? Muchos thankos.
I'm trying to animate a shape. The following is my code.
import SwiftUI
struct ContentView7: View {
@State private var goingLeft = true
@State private var goingUp = true
var body: some View {
ZStack {
Color.green.ignoresSafeArea()
CustomShape(quadDistance: goingUp ? 0: 60.0, horizontalDeviation: 0.0)
.fill(Color.red)
.ignoresSafeArea()
.animation(.easeInOut(duration: 1.0).repeatForever(), value: goingUp)
}.onAppear {
goingUp = false
}
}
}
struct CustomShape: Shape {
var quadDistance: CGFloat
var horizontalDeviation: CGFloat
func path(in rect: CGRect) -> Path {
Path { path in
path.move(to: CGPoint(x: -horizontalDeviation, y: 0))
path.addLine(to: CGPoint(x: rect.maxX + horizontalDeviation , y: 0))
path.addLine(to: CGPoint(x: rect.maxX + horizontalDeviation, y: rect.midY))
path.addLine(to: CGPoint(x: -horizontalDeviation, y: rect.midY))
path.move(to: CGPoint(x: -horizontalDeviation, y: rect.midY))
path.addQuadCurve(to: CGPoint(x: rect.maxX + horizontalDeviation, y: rect.midY), control: CGPoint(x: rect.midX, y: rect.midY + quadDistance))
}
}
}
Well, my intension is to move the center of the convex point up and down. But the shape won't animate itself. What am I doing wrong? Muchos thankos.
I'm trying to show a dialog over ContentView. The dialog view, ShowDialogView, has an ObservedObject object with name and properties.
class User: ObservableObject {
@Published var name = ""
@Published var age: Int = 0
}
struct ShowDialogView: View {
@Binding var isPresented: Bool
@ObservedObject var user: User
/*
@State var name = ""
*/
init(isPresented: Binding<Bool>, user: User) {
self._isPresented = isPresented
self.user = user.searchWord
//_name = State(initialValue: "Kimberly")
}
var body: some View {
VStack {
...
...
}.onAppear {
print("\(user.name)")
}
}
}
struct ContentView: View {
@State var user = User()
@State var showMe = true
var body: some View {
VStack {
...
...
ShowDialogView(isPresented: showMe, user: user)
}
}
}
The dialog view will open with no problem. The problem that I have is that the user object doesn't deliver anything beyond default values. If I somehow set the name property to "Kimberly" before the dialog appears, the app will end up showing no value (""). Even if I try setting an initial value to the name property in the constructor, the app will still show an empty value. What am I doing wrong? I'm sorry I cannot give you a lot of details in the code above. Thank you.
I have a @State variable with an array of strings with which to create instances of TextField. So far, I have the following lines of code.
import SwiftUI
struct ContentView: View {
@State private var names: [String] = ["Jim Thorton", "Susan Murphy", "Tom O'Donnell", "Nancy Smith"]
var body: some View {
HStack {
ForEach($names, id: \.self) { $name in
TextField("", text: $name)
.fixedSize()
.padding(.horizontal, 20.0)
.background(Color.orange.opacity(0.2))
}
}
}
}
I wonder if there is a simple way of aligning instances of TextField horizontally such that one that exceeds the screen width will go to the next line like the following picture?
Thanks.
I often use security-scoped bookmarks when I develop a desktop application in Cocoa. This time, I need to use them in an iOS app, using SwiftUI framework.
I don't quite remember the history, but I use UIDocumentPickerViewController through UIViewControllerRepresentable to let the user select a file. And I have a model where I save file name, file path, its bookmark (Data) with NSKeyedArchiver.. And everything goes well when I run the app in a simulator.
Yet, FileManager says each file in the model does not exist. One of the path is something like the following.
/private/var/mobile/Containers/Shared/AppGroup/749F05F0-12BC-40AC-B5C4-72571145C624/File Provider Storage/Test/somefile.txt
Since it doesn't exist, I cannot even resolve it. How can I resolve the bookmark if a file ends up at the File Provider Storage folder? Do I need a special capability that I don't know about or something? Thanks.
I have created a very simple sample project just to make my point using RealmSwift..
// ContentView.swift //
import SwiftUI
import RealmSwift
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationView {
VStack {
Spacer()
NavigationLink("Listing all meals") {
ListView()
.environmentObject(viewModel)
}
Spacer()
}
}
}
}
// ListView.swift //
import SwiftUI
import RealmSwift
struct ListView: View {
@EnvironmentObject var viewModel: ViewModel
@State var meals = [MealDB]()
var body: some View {
List {
ForEach(meals) { meal in
HStack {
Text("\(meal.title)")
.padding(.leading, 6.0)
Spacer()
Button {
viewModel.model.delete(id: meal.id)
} label: {
Text("Delete")
}
.padding(.trailing, 6.0)
.buttonStyle(.borderless)
}
.onDrag {
return NSItemProvider()
}
}
.onMove(perform: move(from:to:))
}
.onAppear {
updateData()
}
}
func updateData() {
meals.removeAll()
// data from Realm database
for mealItem in viewModel.mealItems {// <<<<<<<<<<
meals.append(mealItem)
}
meals.sort {
(($0).place < (($1).place))
}
}
}
// ViewModel.swift //
import Foundation
import RealmSwift
class ViewModel: ObservableObject {
@Published var model = MealStore()
var mealItems: Results<MealDB> {
model.items
}
}
final class MealStore: ObservableObject {
var config: Realm.Configuration
init() {
config = Realm.Configuration()
}
var realm: Realm {
return try! Realm(configuration: config)
}
var items: Results<MealDB> {
realm.objects(MealDB.self)
}
}
// MealDB.swift //
import Foundation
import RealmSwift
class MealDB: Object, Identifiable {
@objc dynamic var id = ""
@objc dynamic var title = ""
@objc dynamic var order = 0
@objc dynamic var place = 0
override class func primaryKey() -> String? {
"id"
}
}
ListView has a list of meals. Each row comes with a button that lets me delete the corresponding row. And the app will crash inside the updateData function. I have found out that the issue is the way how SwiftUI works and hangs on to the old set of data even after I tap the delete button. So a solution is to 'freeze up' the dataset. And the app won't crash when I tap the delete button.
for mealItem in viewModel.mealItems.freeze() {
...
}
Now, my question is... Are there reasons for not freezing up the dataset? If there is no downside, how come MongoDB just doesn't tell us to do it when we use access a dataset in Realm? Thanks.
I didn't know that Settings Bundle exists till two days ago. Anyway, I've tested it with a simple example. As shown in the screenshot below, I have one group, one text field, one slider and two toggle buttons.
I am able to read the values from all of them except the slider. I wonder if it's a bug? I'm using Xcode 14.2. In the following code, the app won't go inside the if clause for the PSSliderSpecifier key.
import UIKit
class ViewController: UIViewController {
// MARK: - Life cyle
override func viewDidLoad() {
super.viewDidLoad()
let defaultValues = [String: AnyObject]()
UserDefaults.standard.register(defaults: defaultValues)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
/* settings */
fetchSettingBundleData()
}
@objc func fetchSettingBundleData() {
let userDefaults = UserDefaults.standard
if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"), let settings = NSDictionary(contentsOf: settingsURL), let preferences = settings["PreferenceSpecifiers"] as? [NSDictionary] {
var defaultsToRegister = [String: Any]()
for preferenceSpecification in preferences {
if let key = preferenceSpecification["Type"] as? String, let value = preferenceSpecification["Title"] {
defaultsToRegister[key] = value
}
}
userDefaults.register(defaults: defaultsToRegister)
}
if let groupName = userDefaults.string(forKey: "PSGroupSpecifier") {
print("Group name: \(groupName)")
}
if let _ = userDefaults.string(forKey: "PSTextFieldSpecifier") {
if let text = userDefaults.string(forKey: "name_preference") {
print("Textfield \(text)")
}
}
if let _ = userDefaults.string(forKey: "PSToggleSwitchSpecifier") {
if let value = userDefaults.string(forKey: "enabled_preference1") {
print("Toggle \(value)") // 0 or 1
}
}
if let _ = userDefaults.string(forKey: "PSToggleSwitchSpecifier") {
if let value = userDefaults.string(forKey: "enabled_preference2") {
print("Toggle2 \(value)") // 0 or 1
}
}
if let _ = userDefaults.string(forKey: "PSSliderSpecifier") {
print("heck....") // No show
if let value = userDefaults.string(forKey: "slider_preference") {
print("Slider \(value)")
}
}
}
}
I am just playing with NSTextList by creating a sample iOS app. The following is my code.
import UIKit
class ViewController: UIViewController {
lazy var textView: UITextView = {
let textView = UITextView()
textView.text = ""
textView.contentInsetAdjustmentBehavior = .automatic
textView.backgroundColor = .white
textView.font = UIFont.systemFont(ofSize: 20.0)
textView.textColor = .black
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.widthAnchor.constraint(equalToConstant: 600.0),
textView.heightAnchor.constraint(equalToConstant: 600.0)
])
return textView
}()
lazy var button: UIButton = {
let button = UIButton()
button.setTitle("End list", for: .normal)
button.setTitleColor(.white, for: .normal)
button.setTitleColor(.lightGray, for: .highlighted)
button.backgroundColor = .black
button.layer.cornerRadius = 8.0
button.addTarget(self, action: #selector(fixTapped), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.widthAnchor.constraint(equalToConstant: 100.0),
button.heightAnchor.constraint(equalToConstant: 42.0)
])
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBlue
view.addSubview(textView)
view.addSubview(button)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tapGesture)
NSLayoutConstraint.activate([
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20.0)
])
let list = NSTextList(markerFormat: .diamond, options: 0)
list.startingItemNumber = 1
let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
paragraphStyle.textLists = [list]
let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24.0)]
let attributedStr = NSMutableAttributedString(string: "\n\n\n\n\n", attributes: attributes)
textView.textStorage.setAttributedString(attributedStr)
}
@objc func fixTapped() {
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
}
When the app launches itself, I get 5 lines of diamond guys as shown in the following screenshot.
If I keep pressing the delete key with a connected keyboard, the list will be gone as shown below.
But if I press the RETURN key several times, the diamond list will come back as shown below.
So how can I end this June TextList madness? In code, I have the dismissKeyboard function if I can end this madness programmatically.
Thanks,
Señor Tomato Spaghetti
Chief Janitor at
Southeastern Tomato Spaghetti Trade Association
I've been trying to save a selected color with UserDefaults from UIColorPickerViewController. But I run into a color space fiasco. Anyway, here come my lines of code.
class ViewController: UIViewController, UIColorPickerViewControllerDelegate {
@IBOutlet weak var imageView: UIImageView!
@IBAction func selectTapped(_ sender: UIButton) {
let picker = UIColorPickerViewController()
picker.delegate = self
picker.selectedColor = .yellow
picker.supportsAlpha = false
present(picker, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let color = UserDefaultsUIColor.shared.readColor(key: "MyColor") {
print("Color being read: \(color)")
}
}
func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
let color = viewController.selectedColor
print("Selected color: \(color)")
UserDefaultsUIColor.shared.saveColor(color: viewController.selectedColor, key: "MyColor")
}
func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
imageView.backgroundColor = viewController.selectedColor
}
}
class UserDefaultsUIColor {
static let shared = UserDefaultsUIColor()
func saveColor(color: UIColor, key: String) {
let userDefaults = UserDefaults.standard
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) as NSData?
userDefaults.set(data, forKey: key)
} catch {
print("Error UserDefaults: \(error.localizedDescription)")
}
}
func readColor(key: String) -> UIColor? {
let userDefaults = UserDefaults.standard
if let data = userDefaults.data(forKey: key) {
do {
if let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data) {
return color
}
} catch {
print("Error UserDefaults")
}
}
return nil
}
}
I first start out with a yellow color (UIColor.yellow). And I select a color whose RGB values are 76, 212, 158, respectively. And the color picker guy returns the following.
kCGColorSpaceModelRGB 0.298039 0.831373 0.619608 1
And I get the following in reading the saved color data object.
UIExtendedSRGBColorSpace -0.270778 0.84506 0.603229 1
How can I save and read color data objects consistently? I could specify a color space when I save a color. But it doesn't go well.
Muchos thankos
Señor Tomato de Source
I have some lines of code below where I can make multiple selections.
import SwiftUI
struct ContentView: View {
@State private var selectedUsers: Set<String> = []
@State var users = ["Susan", "Kate", "Natalie", "Kimberly", "Taylor", "Sarah", "Nancy", "Katherine", "Nicole", "Linda", "Jane", "Mary", "Olivia", "Barbara"]
var body: some View {
VStack {
List(selection: $selectedUsers) {
ForEach(users, id: \.self) { user in
Text(user)
}
}
.environment(\.editMode, .constant(.active))
}
}
}
So the blue selection symbol appears as shown in the screenshot above. That's good. But that's not what I'm after. I just want to select one row at a time.
import SwiftUI
struct ContentView: View {
@State var selectedUser: String?
@State var users = ["Susan", "Kate", "Natalie", "Kimberly", "Taylor", "Sarah", "Nancy", "Katherine", "Nicole", "Linda", "Jane", "Mary", "Olivia", "Barbara"]
var body: some View {
VStack {
List(selection: $selectedUser) {
ForEach(users, id: \.self) { user in
Text(user)
}
}
.environment(\.editMode, .constant(.active))
}
}
}
In the lines of code above, I only let myself select one row at a time. And I don't get the blue selection symbol. I wonder why? I find two or three websites where they have similar lines of code and where they select one row at a time. And they have the blue selection symbol. Why don't I get it?
Mucho thankos for reading.