Instantiating objects(Entry point) - swift

I am new to swift and Xcode. I have got two swift files which contain's two classes A and B. I need to instantiate an object of Class A to start the program.How would I do that in swift?. I am familiar with Java and I am aware of the main program where the execution starts. How would I do the same in swift? I am not trying to create an iOS or Xcode App.
I have played around with playgrounds and everything works if you put it in a single file. I have created a package and added the swift files. The build is successful but there is no output. The code below is the Source code that I would use in a playground to start the program. How would I do it in an xcode project?
var b = Shop()
b.IssueOrder(quantity: 100, code: "R12")
b.IssueOrder(quantity: 156, code: "L09")
b.IssueOrder(quantity: 13, code: "T58")
I was wondering if there are any swift veterans could help me ??

Look at this structure.
I have created User.swift file in source folder in playground and make use of it in playground.
Class in Source folder : User.swift
import Foundation
public class User {
var firstName : String?
var lastName : String?
public init(_ firstName : String?, _ lastName : String?) {
self.firstName = firstName
self.lastName = lastName
}
public func getFullName() -> String?{
return (firstName ?? "" ) + (lastName ?? "")
}
}
Use it in playground :
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
var user = User("Sagar", "Gondaliya")
print("My FullName : \(user.getFullName()!)")
Output: My FullName : Sagar Gondaliya
Just make sure that class and its method which you want to access should be marked as public.

Turns out this can easily be done using Swift package manager via command line. There are very little resources out there so I thought I will go ahead and write the answer myself.
Create a new Directory and cd into it.
Create a new package using the following command. This will create the project structure for you. It has a main.swift file which will serve as the entry point for the application
swift package init --type executable
Build the project
swift build
Execute the project by running the below command where Project is the name of the directory you created(becomes the name of the project)
.build/debug/Project
You will see the output of the source code in the main.swift file in the terminal

Related

Cannot access Swift Package xcassets

I'm trying to use a color set from a xcassets folder that is inside a Swift Package (src). It doesn't seem to be working. I tested this out by writing a simple view that attempts to make use of the color:
Text("Hello")
.foregroundColor(Color("brandPrimary")
I got an empty view from this code; the text can't find the color.
I've done significant research around the web - reviewing WWDC videos such as Swift packages: Resources and localization, and they seem to suggest that xcassets folder are automatically included as resources. It doesn't work for me.
I tried to add process("Resources/Colors.xcassets") inside my package manifest, but that didn't help either.
From the Color documentation:
init(_ name: String, bundle: Bundle? = nil)
…
bundle
The bundle in which to search for the color resource. If you don’t indicate a bundle, the initializer looks in your app’s main bundle by default.
Your GoodPackage library's assets are not the app's main bundle, so you need to tell the Color initializer which bundle to search.
The Swift package manager's build process automatically creates a Bundle for each target/module that contains assets. Within the module, you can access that generated Bundle using the expression Bundle.module. SwiftPM actually writes Swift code to a file named resource_bundle_accessor.swift in your DerivedData to make this work. The generated source code looks like this:
import class Foundation.Bundle
import class Foundation.ProcessInfo
import struct Foundation.URL
private class BundleFinder {}
extension Foundation.Bundle {
/// Returns the resource bundle associated with the current Swift module.
static let module: Bundle = {
let bundleName = "YourPackageName_YourTargetName"
let overrides: [URL]
#if DEBUG
if let override = ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_URL"] {
overrides = [URL(fileURLWithPath: override)]
} else {
overrides = []
}
#else
overrides = []
#endif
let candidates = overrides + [
// Bundle should be present here when the package is linked into an App.
Bundle.main.resourceURL,
// Bundle should be present here when the package is linked into a framework.
Bundle(for: BundleFinder.self).resourceURL,
// For command-line tools.
Bundle.main.bundleURL,
]
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
return bundle
}
}
fatalError("unable to find bundle named YourPackageName_YourTargetName")
}()
}
As you can see, that static let module property has (default) internal access, so you can only use it from source code within that module. By default, there is no way to access the module's Bundle from outside the module.
One solution is to add a public accessor for the module Bundle in the GoodPackage module. For example, add this to a source file in the GoodPackage module:
import Foundation
extension Bundle {
public var GoodPackage: Bundle { Bundle.module }
}
Then, in your app:
import GoodPackage
...
Text("Hello")
.foregroundColor(Color("brandPrimary", bundle: .GoodPackage))

Trying to figure out Swift Clients for Thrift

I want to utilize thrift from within my new MacOS App. The app is working fine so far as a menubar app.. it takes in a string and lets you save it to memory somewhere... if you click on the clipboard button it saves your string to clipboard.
What I do not understand is.. if I've generated some Swift Client code via the
thrift --gen swift <name_of_thrift_file.thrift>
I get two .swift files, as expected.. AND instructions from the github to rig up the Client object.. here's my Client Object so far.. but I am seeing a error already with the example code. I want to add a status button to the menubar app (anywhere) .. which calls my thrift server for a ping() and goes green once response looks good.
Targeting : Mac OS 12.x+
Thrift Version : v0.16.0
XCode Version : 13.x
happily I hand rolled the library (Thrift) into my project.. for some reason I think the package mangement didn't work.. once added it was a breeze to generate my .thrift files
thrift --gen swift <my_thrift_service>.thrift
once I buttoned all that together in XCode.. the last part was getting a client that worked.. the example in git was showing an error but I got past it with this
AWSBotor3ThriftClient.swift
import Foundation
class AWSBoto3ThriftClient {
var boto3_thrift_client :aws_boto3_accessorClient?
var server_status :Int32
init() {
do {
let transport = try TSocketTransport(hostname: "localhost", port: 9090)
let proto = TBinaryProtocol(on: transport)
let client = aws_boto3_accessorClient(inoutProtocol: proto)
self.boto3_thrift_client = client
self.server_status = try self.boto3_thrift_client!.ping()
} catch {
print("init had a boo boo :(")
self.server_status = 333
self.boto3_thrift_client = nil
}
print(self.server_status)
}
}
S3SyncAppApp.swift
import SwiftUI
#main
struct S3SyncAppApp: App {
#NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#State var currentNumber: String = "1"
var my_little_client: AWSBoto3ThriftClient = AWSBoto3ThriftClient()
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

Swift debugQuickLookObject Xcode 12.4

I'm trying to test debugQuickLookObject I'm using Xcode 12.4 but the sample code given doesn't return a String in the QuickLook Debugger or the console, is debugQuickLookObject still valid?
class User {
var name = "Duane Dibbley"
var age = 28
#objc func debugQuickLookObject() -> Any? {
return "My name is \(name) and I'm \(age)."
}
}
I've tried inheriting from NSObject - no joy, I can't even confirm if the method signature is correct :-s
Code from here: https://www.hackingwithswift.com/example-code/language/how-to-create-quick-look-debug-previews-for-your-custom-types
I managed to get the code working, but only for iOS based projects, code can be found here:
https://github.com/nthState/RealityKitDebugger
I wish I knew why macOS based projects don't work as expected.

Xcode 10 Struct Initializer autoComplete not showing

I am defining my viewModels in a separate files as structs, when i am trying to create an instance of this struct in another file the autocomplete of the memberwise initializer is not showing..
This problem wasn't before(i.e Xcode 9) is it a bug in Xcode 10?
I have seen similar questions like Xcode does not autocomplete memberwise initializer of a Struct
but it's old and the problem was in Xcode 7 or 8 maybe.
However if i place my struct in the file i am attempting to use it, the autocomplete will be shown, so what's the problem ?
I Also tried .init after the struct name with no luck.
Here's my ViewModels :
struct ProfileModels {
struct ViewModels {
struct profile{
let name : URL?
let positionAndCountry : String?
let briefDescription : String?
let hotelInfo : HotelInfo?
}
struct HotelInfo{
let hotelName : String?
let roomClasification : String?
let checkInDate : String?
let checkOutDate : String?
let isCheckInEarly : String?
let isCheckInLate : String?
}
}
}
Update:
As mentioned in the comments that it works fine if the init method called, however sometimes the autocomplete isn't showing with calling the init method...
Anyway for anybody who wants a quick workaround until this bug solved is to use the following:
Create an empty struct (don't worry about the error for now)
example : ProfileModels.viewModels.profile()
In a new line, call the struct and the autocomplete will be shown!, now you can delete the first one.
I don't know why this happened but maybe the compiler after the first line will recognize that this struct missing arguments, so they will appear when the same struct used later...
There has been a bug in Xcode for a while where autocompletion for structs would be finicky. Classes have never had this issue, but I was able to fix the autocompletion by typing .init after the struct name, triggering the autocompletion, and then deleting the .init after. Hope this helps

Private var is accessible from outside the class

This was done in Playground, just to simplify.
class MyPrivateVar
{
private var priv: String?
}
var myInstance = MyPrivateVar()
myInstance.priv = "Something"
No compiler warning. In fact auto-complete is showing priv without a problem.
My understanding is that outside the boundaries of {} of the class, I'm not supposed to be able to see a private anything, func nor var.
Am I missing something?
Access modifiers in Swift are implemented differently than other languages. There are three levels:
private: accessible only within that particular file
internal: accessible only within the module (project)
public: accessible from anywhere
Unless marked otherwise, everything you write is internal by default.
The Swift blog had a post about access control when the features were introduced in beta 4, and Apple's documentation has a chapter as well.
Note: this answer is for Swift 2
The Swift Programming Language states:
Swift provides three different access levels for entities within your
code. These access levels are relative to the source file in which an
entity is defined, and also relative to the module that source file
belongs to.
If you wan't to test private access level with Swift, the following step by step may help you.
1/ Create a new Xcode project.
2/ Create a file, MyPrivateVar.swift, and add the following code in it:
class MyPrivateVar {
private var priv: String? = nil
}
3/ Create a second file, MySecondClass.swift, and add the following code in it:
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
Xcode will immediatly give you a Swift compiler error message:
'MyPrivateVar' does not have a member named 'priv'
4/ Now, remove the two previous files from your project and create a single file TwoClassesInAFile.swift with the following code in it:
class MyPrivateVar {
private var priv : String? = nil
}
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
This time, you will get no Swift compiler error message and you will be able to access MyPrivateVar's priv private property from MySecondClass because priv and MySecondClass are in the same file (your TwoClassesInAFile.swift file).
Furthermore, access levels also work for global variables. For example, Xcode won't give any compiler error if the following code is part of the same ViewController.swift file:
import UIKit
private var globalPrivate : String? = nil
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
globalPrivate = "some string"
println(globalPrivate)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
However, if you define globalPrivate outside of ViewController.swift, Xcode will generate an error message:
Use of unresolved identifier 'globalPrivate'