SwiftUI "No arguments" Error when using website links - ios

I'm developing a simple contacts application, when adding the lines shown below, I receive the error: Argument passed to call that takes no arguments.
let websitetext: String
init(){
self.websitetext = contact.website
}
Below is the entire file with irrelevant data removed.
import Foundation
import SwiftUI
struct ContactsDetailView: View{
let contact: Contact
let websitetext: String //lines referenced
init(){
self.websitetext = contact.website
}
var body: some View {
HStack{
VStack {
Image(contact.imageName)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.clipped()
.cornerRadius(50)
Text(contact.name)
.font(.system(size: 21, weight:.medium, design: .default))
Form{
HStack {
Text ("Phone")
Spacer()
Text(contact.phone)
.foregroundColor(.gray)
.font(.callout)
}
Section{
Link("Website", destination: URL(string: websitetext)!) //Uses the website text variable
}
}
}
}
}
}
struct ResourcesDetailView_Previews: PreviewProvider {
static var previews: some View {
ContactsDetailView(contact: contacts[0]) //ERROR LINE
}
}
Any help to solve this issue would be appreciated!

Related

How to Use the iOS Screen Time API to get a user's total Screen Time (in an app I'm building)

The iOS Screen Time API (using the DeviceActivity framework) is capable of making custom Screen Time reports for users
Documentation: https://developer.apple.com/documentation/deviceactivity
Video Showing this: https://developer.apple.com/videos/play/wwdc2022/110336/
The problem is, beyond an introductory iOS Programming Class that used Dummy Data to create a sample app, I do not know what I'm doing at all.
I need to figure out how to
Request Authorization for a Device API like this
Get the total screen time from a user and display it
This seems simple and is possible, but I'm not even sure which files to put the code from the Documentation, let alone deal with real data from a User.
Here's what I have so far:
ContentView
import SwiftUI
import DeviceActivity
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Welcome to the first view")
}
.toolbar {
NavigationLink(destination: APICall()) {
Text("Next")
}
}
.navigationBarTitle("First View")
}
}
}
struct APICall: View {
#State private var screenTime: Double? = nil
#State private var error: Error? = nil
var body: some View {
VStack {
HStack {
Image(systemName: "clock")
.resizable()
.frame(width: 50, height: 50)
.aspectRatio(contentMode: .fit)
.padding(.leading, 20)
VStack(alignment: .leading) {
if screenTime != nil {
Text("Total screen time: \(screenTime!) hours")
.font(.title)
.foregroundColor(.primary)
} else {
Text("Press the button to fetch screen time")
.font(.title)
.foregroundColor(.secondary)
}
}
Spacer()
}
.padding(.vertical, 20)
Button(action: fetchScreenTime) {
Text("Fetch screen time")
.font(.title)
.foregroundColor(.blue)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [.red, .orange]), startPoint: .topLeading, endPoint: .bottomTrailing))
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.white, lineWidth: 4)
)
}
if error != nil {
Text("Error: \(error!.localizedDescription)")
}
}
}
func fetchScreenTime() {
//WHAT DO I DO FOR THIS
}
}
AuthRequest
import Foundation
import SwiftUI
import DeviceActivity
import FamilyControls
#main
struct Worklog: App {
let center = AuthorizationCenter.shared
var body: some Scene {
WindowGroup {
VStack {Text("Hi")}
.onAppear {
Task {
do {
try await center.requestAuthorization(for: //WHAT DO I CALL HERE?
)
} catch {
print("Failed with \(error)")
}
}
}
}
}
}
do {
try await center.requestAuthorization(
for: /* can be .individual to look at your
own screen time or .child if this
is going on a child's device */)
} catch {
print("Failed with \(error)")
}
In fetchScreenTime(), you're going to make an extension to your app that uses the DeviceActivityMonitor. I'll update when I figure out how they fit together

SwiftUI: How can I add a new component to the list? Idea: Click the "plus"-button, enter a "Text", store it and... it's been added to the List

So here is the declaration of the variable (passwordNewName):
#State var passwordNewName = ""
It is being updated from the input of a TextField which I coded to accept user's data.
So the idea is that the String which is stored in the variable will - eventually - get transmitted into this List():
If I understand it right, the .setname files are stored inside this static func all() database or whatever these [*braces*] are:
Basically, the String-variable passwordNewName should somehow be added to these [braces] automatically... I am really so lost.((
Thank you in advance!!!
According to the question it looks that you want to update the list along with to send/save it permanently. The actual solution for this problem is to use ObservableObject class with #Published property. But the code below will give you more understanding of scenario.
import SwiftUI
struct ContentView: View {
#State private var lernSet_array: [Lernset] = Lernset.get_all()
var body: some View {
VStack(spacing: 0) {
HStack {
Text("Collection")
Button {
lernSet_array.append(Lernset(setname: "Testing", color: "black"))
} label: {
Image(systemName: "plus")
.resizable()
.frame(width: 30, height: 30)
.padding()
}
}
ScrollView {
VStack(alignment: .leading) {
ForEach(lernSet_array) { lernset in
HStack {
Image(systemName: "folder")
.resizable()
.frame(width: 80, height: 80)
.foregroundColor(.gray)
Text(lernset.setname)
}
}
}
}
}.onChange(of: lernSet_array) { newValue in
// Update this database, and somehow store the data
// and save it permanently… even after restarting the phone
print("Update this database, and somehow store the data and save it permanently… even after restarting the phone")
print(lernSet_array.count)
}
}
}
struct Lernset: Identifiable, Equatable {
let id = UUID()
let setname: String
let color: String
static func get_all() -> [Lernset] {
return [Lernset(setname: "Biology - Tail", color: "green"),
Lernset(setname: "Math - Tail", color: "blue"),
Lernset(setname: "Phy - Tail", color: "black"),
]
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

Why can't I populate an array with function call in my SwiftUI code?

I am trying to populate an array ingredients with a function call to networkManager.buildIngredients() within my view but I am getting the error message Type '()' cannot conform to 'View'. I am not too familiar with SwiftUI at the moment and I would appreciate any help or guidance.
Here is my SwiftUI struct;
struct DetailsView: View {
#ObservedObject var networkManager = NetworkManager()
#State var ingredients: [String]
let urlString: String
var body: some View {
List(networkManager.cocktails) { cocktail in
VStack(alignment: .center) {
HStack(alignment: .center) {
Text(cocktail.strDrink + " -")
.navigationTitle("Cocktail by first letter")
.frame(alignment: .center)
Text(cocktail.strAlcoholic)
.frame(alignment: .center)
}
WebImage(url: URL(string: cocktail.strDrinkThumb))
.resizable()
.frame(width: 200, height: 200, alignment: .center)
Text("~ Ingredients List ~").frame(alignment: .center)
ingredients = networkManager.buildIngredients(cocktail)
ForEach(ingredients, id: \.self) { ingredient in
Text(ingredient)
}
}
}
.onAppear {
self.networkManager.fetchData(urlString)
}
}
}
struct DetailsView_Previews: PreviewProvider {
static var previews: some View {
DetailsView(urlString: "www.google.com")
}
}

I'm having an issue changing Views in SwiftUI using an if/else statement for a login view

I'm having trouble changing views when a username and password is successfully entered. I know the username and password works because the print statement is executed. Its a basic login type form.
import SwiftUI
struct LoginView: View {
#ObservedObject var networkManager: NetworkManager = NetworkManager()
#State var username: String = ""
#State var password: String = ""
var body: some View {
NavigationView {
VStack {
Image("dashlogovert")
.resizable()
.scaledToFit()
.frame(width: 280.0, height: 280.0, alignment: .top)
Form {
TextField("Username", text: $username)
SecureField("Password", text: $password)
Button(action: {
self.AttempLogin()
})
{
Text("Login")
.fontWeight(.bold)
.frame(width: 300, height: 30, alignment: .center)
.font(.title)
.padding()
.background(Color(red: 132/255, green: 203/255, blue: 161/255))
.foregroundColor(.white)
}
}
}
.navigationBarTitle("Login")
}
}
func AttempLogin(){
self.networkManager.loginFunction(username: self.username, password: self.password){
if self.networkManager.loggedIn {
print("You are logging in");
Dashboard()
} else {
print("You aren't logging in");
FailedLogin()
}
}
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
Dashboard() is the new view I will take the user to when they successful logon, and fail is also a view.
Also what is the best way to do this if I have done it a really bad way.
You can pass back your logged in state from loginFunction() using #escaping closure if it’s asynchronous task, and once you have that state you can pass it back to your view body by using closure again as a parameter in AttemptLogin() function, and assign that new state value to #State property wrapper, which will call body refresh and check for updated state.
Check below code-:
import SwiftUI
enum LoginState:String {
case failed
case success
case unknownState
}
class NetworkManager:ObservableObject{
func loginFunction(username:String,password:String,closure: #escaping (String)->()){
closure(LoginState.failed.rawValue)
}
}
struct LoginView: View {
#ObservedObject var networkManager: NetworkManager = NetworkManager()
#State var username: String = ""
#State var password: String = ""
#State var isLoggedIn:String = LoginState.unknownState.rawValue
var body: some View {
NavigationView {
VStack {
Image("dashlogovert")
.resizable()
.scaledToFit()
.frame(width: 280.0, height: 280.0, alignment: .top)
Form {
TextField("Username", text: $username)
SecureField("Password", text: $password)
Button(action: {
self.AttempLogin { state in
isLoggedIn = state
}
})
{
Text("Login")
.fontWeight(.bold)
.frame(width: 300, height: 30, alignment: .center)
.font(.title)
.padding()
.background(Color(red: 132/255, green: 203/255, blue: 161/255))
.foregroundColor(.white)
}
if isLoggedIn == LoginState.success.rawValue{
Dashboard()
}
if isLoggedIn == LoginState.failed.rawValue{
FailedLogin()
}
}
}
.navigationBarTitle("Login")
}
}
func AttempLogin(_ closure: #escaping (String)->()){
self.networkManager.loginFunction(username: self.username, password: self.password){ loginState in
if loginState == LoginState.success.rawValue {
print("You are logging in");
closure(loginState)
}
if loginState == LoginState.failed.rawValue {
print("You aren't logging in");
closure(loginState)
}
}
}
}
struct Dashboard:View{
var body: some View{
Text("Dashboard")
}
}
struct FailedLogin:View{
var body: some View{
Text("Login")
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
I have taken NetworkManager and other classes as dummy on my side.You need to write your logic accordingly.

Cannot get ScrollView to working within SwiftUI using a VStack

Every time I try to add scrollview, or navigational view to my swiftui code, it causes the app to not load anything from the api. Currently I'm using the OMDB api. Pasted is my movie store and my ContentView. Currently I'm using a custom card view to display the image and the title from the movie store, but after trying to enable scroll view the whole preview of the rendered application goes completely white. And nothing will show up again until I comment out the scroll view. I have tried using a horizontal view and a simple image and text vstack to see if the card view was somehow messing things up with the scroll view.
The tutorial that I have followed for getting this far with some modifications is here: https://www.youtube.com/watch?v=NvyAN81YcO0
Currently I'm running Xcode 11.6.
import Foundation
struct MovieResponse : Decodable{
let movies: [Movie]
private enum CodingKeys:String, CodingKey{
case movies = "Search"
}
}
struct Movie: Decodable{
let imdbID :String
let title: String
let poster: String
let type: String
let year: String
private enum CodingKeys: String, CodingKey{
case imdbID
case title = "Title"
case poster = "Poster"
case type = "Type"
case year = "Year"
}
}
class MovieStore: ObservableObject{
#Published var movies: [Movie]? = [Movie]()
func getAll(){
guard let url = URL(string: "") else{
fatalError("Invalid url")
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else{
return
}
let movieResponse = try? JSONDecoder().decode(MovieResponse.self, from:data)
if let movieResponse = movieResponse {
DispatchQueue.main.async{
self.movies = movieResponse.movies
}
}
}.resume()
}
}
import SwiftUI
struct CardView: View {
var image: URLImage
var type: String
var title: String
var year: String
var body: some View {
VStack {
image
.aspectRatio(contentMode: .fit)
HStack {
VStack(alignment: .leading) {
Text(type)
.font(.headline)
.foregroundColor(.secondary)
Text(title)
.font(.title)
.fontWeight(.black)
.foregroundColor(.primary)
.lineLimit(3)
Text(year)
.font(.caption)
.foregroundColor(.secondary)
}
.layoutPriority(100)
Spacer()
}
.padding()
}
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color(.sRGB, red: 150/255, green: 150/255, blue: 150/255, opacity: 0.1), lineWidth: 1)
)
.padding([.top, .horizontal])
}
}
struct ContentView: View {
#ObservedObject var store: MovieStore
var body: some View {
// ScrollView{
HStack{
ForEach(store.movies ?? [Movie](), id: \.imdbID){ movie in
VStack{
// URLImage(url: movie.poster)
// .frame(width: 100, height: 150)
// Text(movie.title)
// .frame(maxHeight: .infinity, alignment: .top)
CardView(image: URLImage(url:movie.poster), type: movie.type, title: movie.title, year: movie.year)
}
}
}
// }
.onAppear(){
self.store.getAll()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(store: MovieStore())
}
}
Edit:
I was able to generate the app with scrolling with the movies popping up from the api. But only with the list attribute. I noticed that I am getting an error, and am not sure if it affecting the pinging of the api.
2020-08-01 18:28:26.274953-0500 Nyx[19421:1105938] Task <B38BF736-765C-4C69-9ADE-AD889ED7BBE5>.<4> finished with error [-1002] Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSUnderlyingError=0x600003c14000 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}, NSErrorFailingURLStringKey=N/A, NSErrorFailingURLKey=N/A, NSLocalizedDescription=unsupported URL}

Resources