Post

Replies

Boosts

Views

Activity

Issue with Keyboard Avoidance for Sheet View in SwiftUI
I am currently working on a comments section modeled after TikTok's/Instagram's comment sections for a media app. The view is a sheet view that is presented as follows: .sheet(isPresented: $showChat) { TakesChatView(viewModel: viewModel) .presentationDetents([.medium, .large]) .presentationDragIndicator(.hidden) .overlay( VStack { RoundedRectangle(cornerRadius: 2) .fill(Color.gray) .frame(width: 40, height: 5) .padding(.top, 15) .opacity(0.8) Label("Chat", systemImage: "message.badge") .lineLimit(nil) .padding(.top, 5) .padding([.leading, .trailing], 16) Divider() .padding(.top, 5) .padding([.leading, .trailing], 16) Spacer() } .frame(maxWidth: .infinity, alignment: .top) ) }.ignoresSafeArea(.keyboard, edges: .bottom) However, some issues arise regarding keyboard avoidance. Currently, when the user taps on the TextField to type a comment, the keyboard shifts the entire view upwards as it pops up. Instead, I need it where I can still view the comments without the keyboard affecting their placement when it pop up. Below is the associated code for the comment view: struct TakesChatView: View { @ObservedObject var viewModel: TakeCommentViewModel @FocusState var focus: Bool @State private var selectedMedia: [PhotosPickerItem] = [] @State private var selectedImageData: [Data] = [] @State private var selectedGIFData: [Data] = [] @State private var selectedVideoData: [Data] = [] var textFieldNotEmpty: Bool { !viewModel.textToPost.isEmpty || !selectedImageData.isEmpty || !selectedGIFData.isEmpty || !selectedVideoData.isEmpty } var body: some View { GeometryReader { _ in ZStack { VStack { contentView commentTextField .padding(.top,5) } } } .ignoresSafeArea(.keyboard, edges: .bottom) .background(Color.containerBackground) .onChange(of: viewModel.focus) { focus in self.focus = focus } .onChange(of: selectedMedia) { _ in loadMedia() } } var contentView: some View { VStack { Spacer().frame(height: 105) ScrollViewReader { scroll in ScrollView(showsIndicators: true) { ForEach(viewModel.comments, id: \.self) { comment in TakeCommentView( comment: comment, viewModel: self.viewModel ) .padding(.horizontal, 10) .id(comment.documentID) } .onChange(of: viewModel.commentAdded) { id in scroll.scrollTo(id, anchor: .bottom) viewModel.commentAdded = nil } } .scrollDismissesKeyboard(.immediately) } } } } extension TakesChatView { var commentTextField: some View { VStack { mediaPreview HStack { TextField("Type your comment", text: $viewModel.textToPost, axis: .vertical) .keyboardType(.twitter) .padding([.leading, .vertical], 6) .focused($focus) PhotosPicker(selection: $selectedMedia, matching: .any(of: [.images, .videos]), photoLibrary: .shared()) { ComposeType.media.image .frame(width: 40, height: 40, alignment: .center) } .onAppear { selectedMedia.removeAll() selectedImageData.removeAll() selectedGIFData.removeAll() selectedVideoData.removeAll() } postButton } .border(.lightGray, width: 1, cornerRadius: 10) .padding([.bottom, .horizontal], 10) } } } I have tried using .ignoresSafeAres(), .safeAreaInset(), and custom keyboard observer functions but to no avail. How do I fix this issue?
0
0
250
Sep ’24
SwiftUI SideMenu Navigation Issue
I am currently refactoring my app's side menu to be more like Twitter's. I have the UI down in terms of how the side menu looks and appears, but the issue is navigating to a view from the side menu. The views that a user can go to from the side menu are a mix of SwiftUI views & UIKit View Controllers. As of right now, when a user navigates to a view from the side menu, it presents it modally as a sheet. I want it to have regular navigation, where the user goes to the view displayed in full screen and can tap on the back button to go back to the previous view. Here is the associated code: SideMenuView.swift SideMenuViewModel.swift How can I modify the navigation logic to be like Twitter's? I've been stuck for days trying to find a fix but it has been a struggle.
1
0
424
Jun ’24
Error When Saving Video To Camera Roll
I am working on enabling the option for users to save a video from a post in a social media app to their cameral roll. I am trying to use PHPhotoLibrary to perform the task similarly to how I did the functionality for saving images and gifs. However, when I try to perform the task with the code as is, I get the following errors: Error Domain=PHPhotosErrorDomain Code=-1 "(null)" The operation couldn’t be completed. (PHPhotosErrorDomain error -1.) The implementation is as follows: Button(action: { guard let videoURL = URL(string: media.link.absoluteString) else { print("Invalid video url.") return } PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL) print("Video URL: \(videoURL)") }) { (success, error) in if let error = error { debugPrint(error) print(error.localizedDescription) } else { print("Video saved to camera roll!") } } }) { Text("Save Video") Image(systemName: "square.and.arrow.down") } The video URL is successfully fetched dynamically from the post, but there's an issue with storing it locally in the library. What am I missing?
1
0
729
Feb ’24
Double Tap Not Being Detected Anywhere In Video
I am working on implementing tap gestures in a dynamic VideoPlayer made with AVKit. I intend to have it be when a video is viewed in a feed (this is for a social media app), the video plays without sound. Tapping on the video once enables sound, tapping on the video twice makes it full screen. Currently, the single tap works. However, the double tap isn't detected unless I tap on the top right corner of the video. import SwiftUI import AVKit struct VideoPlayerView: View { @StateObject private var viewModel: VideoPlayerViewModel init(url: URL, isFeedView: Bool = true) { _viewModel = StateObject(wrappedValue: .init(url: url, isFeedView: isFeedView)) } var body: some View { ZStack { if let player: AVPlayer = viewModel.player { VideoPlayer(player: player) .onAppear { // Start playing or resume from the last known position if in feed view if viewModel.isFeedView { if let lastKnownTime = viewModel.lastKnownTime { player.seek(to: CMTime(seconds: lastKnownTime, preferredTimescale: 600)) } player.play() player.volume = 0 // Set volume to 0 for feed view } } .onDisappear { // Pause the video and store the last known time viewModel.lastKnownTime = player.currentTime().seconds player.pause() } .contentShape(Rectangle()) .gesture(TapGesture(count: 2).onEnded { print("Double tap detected") viewModel.isFullScreen.toggle() }) .simultaneousGesture(TapGesture().onEnded { print("Single tap detected") player.volume = 1 // Set volume to 1 }) } } .maxSize() .fullScreenCover(isPresented: $viewModel.isFullScreen) { AVPlayerViewControllerRepresented(viewModel: viewModel) } } } class VideoPlayerViewModel: ObservableObject { @Published var player: AVPlayer? @Published var lastKnownTime: Double? @Published var isFullScreen: Bool = false @Published var isFeedView: Bool init(url: URL, isFeedView: Bool = true) { player = AVPlayer(url: url) lastKnownTime = nil self.isFeedView = isFeedView if isFeedView { registerForPlaybackEndNotification() } } private func registerForPlaybackEndNotification() { NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil) { [weak self] _ in self?.videoDidFinish() } } private func videoDidFinish() { // Replay logic for feed view if isFeedView, let player = player { player.seek(to: .zero) player.play() } } } I tried using .contentShape(Rectangle()) as I read that it expands the detectable area for taps, but to no avail. How can I have it so that when I double tap anywhere in the video, it's detected and the video goes full screen?
0
0
626
Jan ’24
Inputted values in SignUpView won't save to backend
I am currently refactoring the signup process for a sports media app in SwiftUI and having issues trying to have it save data associated with the new user to the backend (comprised of a mix of Firebase and a custom backend) via a signup function in an AuthService class. Whenever I enter the required info to create an account (email, username, password, etc.), I get the following errors Error: The data couldn’t be read because it is missing. Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "user", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"user\", intValue: nil) (\"user\").", underlyingError: nil)) Here is all the relevant code: SignUpView.swift AuthService.swift Signup.swift For AuthService, the signup function is what's relevant as I call it in SignUpView and SignUp has the definition for AccountSignUp which is called in the other two files. What is not being read correctly in the data? What is missing and what can be done to fix it such that the info will be saved to the backend? All help will be greatly appreciated!
0
0
393
Nov ’23
Having Proper Message Functionality with Parse, UIKit and MessageKit
For my iOS Social Media App project, I am currently working on the Direct Messaging feature of the app. As of making this post, I have the basic functionality working where you can send messages to other users in the app. However, there are a few issues I am experiencing. 1.) When I go to the chat to send a message it shows two text input bars instead of one. It could have something to do with me also using InputBarAccessoryView but I am not sure how to go about removing one of the two input bars so there's only one. 2.) Being able to see the other user's texts and replies. I can send a message to the user but said user won't be able to see it and vice versa for some reason I haven't been able to fetch and load chat history properly. 3.) The chats don't have their own unique messages. If I send a message to one user, it shows up in my chats with other users as well rather than each chat having its own unique messages. Here is my code associated with Messaging import UIKit import MessageKit import InputBarAccessoryView import Parse struct Message: MessageType { var sender: SenderType var messageId: String var sentDate: Date var kind: MessageKind } class ChatViewController: MessagesViewController, MessagesDataSource, MessagesLayoutDelegate, MessagesDisplayDelegate, InputBarAccessoryViewDelegate { let currentUser = PFUser.current()! var otherUser: PFUser! var messages = [MessageType]() var inputBar = InputBarAccessoryView() override func viewDidLoad() { super.viewDidLoad() // Set up the other user let query = PFUser.query() query?.whereKey("objectId", notEqualTo: currentUser.objectId!) query?.findObjectsInBackground(block: { (objects, error) in if let users = objects as? [PFUser], let user = users.first { self.otherUser = user // Retrieve previous messages from Parse let messageQuery = PFQuery(className: "Message") messageQuery.whereKey("sender", equalTo: self.currentUser) messageQuery.whereKey("recipient", equalTo: self.otherUser!) let recipientQuery = PFQuery(className: "Message") recipientQuery.whereKey("sender", equalTo: self.otherUser!) recipientQuery.whereKey("recipient", equalTo: self.currentUser) let query = PFQuery.orQuery(withSubqueries: [messageQuery, recipientQuery]) query.findObjectsInBackground { (objects, error) in if let messages = objects { for message in messages { let sender = message["sender"] as! PFUser let text = message["text"] as! String let sentDate = message.createdAt! let messageKind = MessageKind.text(text) let messageSender: Sender do { try sender.fetchIfNeeded() messageSender = Sender(senderId: sender.objectId!, displayName: sender.username ?? "") } catch { messageSender = Sender(senderId: sender.objectId!, displayName: "Unknown") print("Error fetching sender: \(error.localizedDescription)") } let message = Message(sender: messageSender, messageId: message.objectId!, sentDate: sentDate, kind: messageKind) self.messages.append(message) print("Fetched previous messages!") } self.messagesCollectionView.reloadData() self.messagesCollectionView.scrollToLastItem(animated: false) } } } }) // Configure the messages collection view and input bar messagesCollectionView.messagesDataSource = self messagesCollectionView.messagesLayoutDelegate = self messagesCollectionView.messagesDisplayDelegate = self view.addSubview(inputBar) inputBar.delegate = self inputBar.inputTextView.placeholder = "Type a message..." inputBar.sendButton.setTitle("Send", for: .normal) inputBar.sendButton.setTitleColor(view.tintColor, for: .normal) inputBar.sendButton.addTarget(self, action: #selector(sendButtonPressed), for: .touchUpInside) inputBar.translatesAutoresizingMaskIntoConstraints = false inputBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true inputBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true inputBar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true } func currentSender() -> SenderType { return Sender(senderId: currentUser.objectId!, displayName: currentUser.username ?? "") } func numberOfSections(in messagesCollectionView: MessagesCollectionView) -> Int { return messages.count } func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType { return messages[indexPath.section] } @objc func sendButtonPressed() { let messageText = inputBar.inputTextView.text.trimmingCharacters(in: .whitespacesAndNewlines) guard !messageText.isEmpty else { return } let message = Message(sender: currentSender(), messageId: UUID().uuidString, sentDate: Date(), kind: .text(messageText)) messages.append(message) inputBar.inputTextView.text = "" messagesCollectionView.reloadData() messagesCollectionView.scrollToLastItem(animated: true) print("Message sent!") // Save the message to Parse let parseMessage = PFObject(className: "Message") parseMessage["sender"] = currentUser parseMessage["recipient"] = otherUser parseMessage["text"] = messageText parseMessage.saveInBackground() print("Message saved!") } func inputBar(_ inputBar: InputBarAccessoryView, textViewTextDidChangeTo text: String) { if text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { inputBar.sendButton.isEnabled = false } else { inputBar.sendButton.isEnabled = true } } func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String) { sendButtonPressed() } } The above code is for all the messaging functionality such as sending texts, receiving messages, and loading and showing chat history. All help would be greatly appreciated!
0
0
891
Apr ’23
Having In-App Notifications Vary By User in App
I am working on in-app notifications for my social media app that I'm programming using Parse and UIKit on Xcode 14.2. My main issue is that while the notification system itself is working, it's not varying by the user. For example, say there are two users, User1 and User2. The way the notifications should be set up is when User1 likes User2's post or leaves a comment on User2's post, only User2 gets a notification saying "User1 liked your post!" or "User1 left a comment on your post!". However as of right now, when User1 likes or comment's on User2's post, User1 gets the notification saying "User1 liked your post!". Here is the code that implements notifications in my app: import UIKit import Parse class NotificationViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! var notifications: [PFObject] = [] override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self tableView.dataSource = self NotificationCenter.default.addObserver(self, selector: #selector(didLikePost(_:)), name: NSNotification.Name("PostLikedByOtherUser"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(madeCommentOnPost(_:)), name: NSNotification.Name("CommentMade"), object: nil) let notificationClass = PFObject(className: "Notification") notificationClass["user"] = PFUser.current() notificationClass["fromUser"] = PFUser.current() notificationClass["post"] = PFObject(className: "Post") notificationClass.saveInBackground { (success, error) in if success { print("Notification class created successfully") } else if let error = error { print("Error creating notification class: \(error.localizedDescription)") } } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let query = PFQuery(className: "Notification") query.whereKey("user", equalTo: PFUser.current()!) query.includeKey("fromUser") query.includeKey("post") query.order(byDescending: "createdAt") query.findObjectsInBackground { (objects, error) in if let error = error { print("Error querying for notifications: \(error.localizedDescription)") } else if let notifications = objects { self.notifications = notifications self.tableView.reloadData() } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return notifications.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "NotificationCell", for: indexPath) as! NotificationCell let notification = notifications[indexPath.row] let fromUser = notification["fromUser"] as! PFUser let post = notification["post"] as? PFObject cell.usernameLabel.text = fromUser.username if let username = fromUser.username, let post = post { if let likes = post["likes"] as? [PFObject], let _ = likes.first(where: { $0["liker"] as? String == PFUser.current()?.objectId }), post["user"] as? String == PFUser.current()?.objectId { cell.messageLabel.text = "You liked your own post." } else if let comments = post["comments"] as? [PFObject], let _ = comments.first(where: { $0["commenter"] as? String == PFUser.current()?.objectId }) { cell.messageLabel.text = "You liked \(username)'s post." } else if let _ = notification["comment"] { cell.messageLabel.text = "\(username) commented on your post." } else { cell.messageLabel.text = "\(username) liked your post." } } return cell } @objc func didLikePost(_ notification: Notification) { guard let post = notification.object as? PFObject, let postOwner = post["user"] as? PFUser, let liker = notification.userInfo?["liker"] as? PFUser, postOwner.objectId != liker.objectId, postOwner.objectId == PFUser.current()?.objectId else { return } let notificationObject = PFObject(className: "Notification") notificationObject["user"] = postOwner notificationObject["fromUser"] = liker notificationObject["post"] = post notificationObject.saveInBackground { (success, error) in if success { print("Successfully created notification") } else if let error = error { print("Error creating notification: \(error.localizedDescription)") } } } @objc func madeCommentOnPost(_ notification: Notification) { guard let comment = notification.object as? PFObject, let post = comment["post"] as? PFObject, let postOwner = post["user"] as? PFUser, let commenter = notification.userInfo?["commenter"] as? PFUser, postOwner.objectId != commenter.objectId, postOwner.objectId == PFUser.current()?.objectId else { return } let notificationObject = PFObject(className: "Notification") notificationObject["user"] = postOwner notificationObject["fromUser"] = commenter notificationObject["post"] = post notificationObject.saveInBackground { (success, error) in if success { print("Successfully created notification") } else if let error = error { print("Error creating notification: \(error.localizedDescription)") } } } deinit { NotificationCenter.default.removeObserver(self) } } I would really appreciate all the help on here.
1
0
502
Apr ’23
Unable to get alerts to show on simulator screen
I am currently working on a social media app and so far I have been able to make a LoginViewController & a SignUpVIewController. Right now I am currently trying to have it where on the SignUpViewController if not all required fields are filled out then the app will display an alert. However, every time i run the app the alert doesn't show up on the simulator screen. Same goes for Xcode's terminal. My code for the SignUpViewController is as follows: import UIKit import Parse class SignUpViewController: UIViewController {   @IBOutlet weak var emailTextField: UITextField!       @IBOutlet weak var usernameTextField: UITextField!       @IBOutlet weak var passwordTextField: UITextField!       @IBOutlet weak var confirmPasswordFieldText: UITextField!       @IBOutlet weak var signUpButton: UIButton!           override func viewDidLoad() {     super.viewDidLoad()   }           @IBAction func signUpButtonTapped(_ sender: UIButton)   {     let username = usernameTextField.text     let password = passwordTextField.text     let email = emailTextField.text     let confirmpw = confirmPasswordFieldText.text           if username == "" || password == "" || email == "" || confirmpw == ""     {       let alert = UIAlertController(title: "Error", message: "Please fill out all required fields", preferredStyle: .alert)       alert.addAction(UIAlertAction(title: "OK", style: .default,handler: nil))       present(alert, animated: true, completion: nil)       return     }           let newUser = User(username: username!, password: password!, email: email!)   }         }     class User {   var username: String   var password: String   var email: String       init(username: String, password: String, email: String) {     self.username = username     self.password = password     self.email = email   } } All the buttons are connected to the correct spots. Would greatly appreciate if anyone can help me fix this.
1
0
443
Feb ’23
Repeated Crash Reports when I add code to a project
I am doing the Swift Landmarks app tutorial on Xcode 13.2.1 on my 2019 Macbook Pro. I am up to the Working with UI Controls section. Every time I add the following lines of code to ProfileSummary.swift: @EnvironmentObject var modelData: ModelData . . . Divider()                   VStack(alignment: .leading)         {                   Text("Recent Hikes")                     .font(.headline)                   HikeView(hike: modelData.hikes[0])         } and I then try to view the preview I repeatedly get a crash report and everything stops working. When I remove those lines of code everything goes back to working fine. The crash report is in this attachment: Translated Crash Report ^ That is the translated report. If you guys would like the full report I will post it. I am stuck and don't know what to do any help will be appreciated!
1
0
1.3k
Feb ’22
Thread 1: Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value
In the fps im making, I am now working on mapping the levels. I have already made the walls and provided texture on them, and now I'm doing the same to the floor. I am able to code a red floor, however whenever I try to code texture on it I get the following error: "Thread 1: Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value" The code appears at this line in ViewController.swift return Textures(loader: { name in Bitmap(image: UIImage(named: name)!)!}) Here's the full code for ViewController.swift: import Engine private let joystickRadius: Double = 40 private let maximumTimeStep: Double = 1 / 20 private let worldTimeStep: Double = 1 / 120 private func loadTextures() -> Textures {   return Textures(loader: { name in Bitmap(image: UIImage(named: name)!)!}) } private func loadMap() -> Tilemap {   let jsonURL = Bundle.main.url(forResource: "Map", withExtension: "json")!   let jsonData = try! Data(contentsOf: jsonURL)   return try! JSONDecoder().decode(Tilemap.self, from: jsonData) } class ViewController: UIViewController {   private let imageView = UIImageView()   private let panGesture = UIPanGestureRecognizer()   private var world = World(map: loadMap())   private var lastFrameTime = CACurrentMediaTime()   private let textures = loadTextures()   override func viewDidLoad() {     super.viewDidLoad()     setUpImageView()     let displayLink = CADisplayLink(target: self, selector: #selector(update))     displayLink.add(to: .main, forMode: .common)     view.addGestureRecognizer(panGesture)   }   private var inputVector: Vector {     switch panGesture.state {     case .began, .changed:       let translation = panGesture.translation(in: view)       var vector = Vector(x: Double(translation.x), y: Double(translation.y))       vector /= max(joystickRadius, vector.length)       panGesture.setTranslation(CGPoint(         x: vector.x * joystickRadius,         y: vector.y * joystickRadius       ), in: view)       return vector     default:       return Vector(x: 0, y: 0)     }   }   @objc func update(_ displayLink: CADisplayLink) {     let timeStep = min(maximumTimeStep, displayLink.timestamp - lastFrameTime)     let inputVector = self.inputVector     let rotation = inputVector.x * world.player.turningSpeed * worldTimeStep     let input = Input(speed: -inputVector.y, rotation: Rotation(sine: sin(rotation), cosine: cos(rotation)))     let worldSteps = (timeStep / worldTimeStep).rounded(.up)     for _ in 0 ..< Int(worldSteps) {       world.update(timeStep: timeStep / worldSteps, input: input)     }     lastFrameTime = displayLink.timestamp     let width = Int(imageView.bounds.width), height = Int(imageView.bounds.height)     var renderer = Renderer(width: width, height: height, textures: textures)     renderer.draw(world)     imageView.image = UIImage(bitmap: renderer.bitmap)   }   func setUpImageView() {     view.addSubview(imageView)     imageView.translatesAutoresizingMaskIntoConstraints = false     imageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true     imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true     imageView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true     imageView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true     imageView.contentMode = .scaleAspectFit     imageView.backgroundColor = .black     imageView.layer.magnificationFilter = .nearest   } } Here's the code for other files that deal with the texturing of the floor and the level in general: Textures.swift {   case wall, wall2   case floor, ceiling } public struct Textures {   private let textures: [Texture: Bitmap] } public extension Textures {   init(loader: (String) -> Bitmap)   {     var textures = [Texture: Bitmap]()     for texture in Texture.allCases     {       textures[texture] = loader(texture.rawValue)     }     self.init(textures: textures)   }   subscript(_ texture: Texture) -> Bitmap   {     return textures[texture]!   } } Renderer.swift:   public private(set) var bitmap: Bitmap   private let textures: Textures   public init(width: Int, height: Int, textures: Textures) {     self.bitmap = Bitmap(width: width, height: height, color: .black)     self.textures = textures   } } public extension Renderer {   mutating func draw(_ world: World) {     let focalLength = 1.0     let viewWidth = Double(bitmap.width) / Double(bitmap.height)     let viewPlane = world.player.direction.orthogonal * viewWidth     let viewCenter = world.player.position + world.player.direction * focalLength     let viewStart = viewCenter - viewPlane / 2     // Cast rays     let columns = bitmap.width     let step = viewPlane / Double(columns)     var columnPosition = viewStart     for x in 0 ..< columns {       let rayDirection = columnPosition - world.player.position       let viewPlaneDistance = rayDirection.length       let ray = Ray(         origin: world.player.position,         direction: rayDirection / viewPlaneDistance       )       let end = world.map.hitTest(ray)       let wallDistance = (end - ray.origin).length               // Draw wall       let wallHeight = 1.0       let distanceRatio = viewPlaneDistance / focalLength       let perpendicular = wallDistance / distanceRatio       let height = wallHeight * focalLength / perpendicular * Double(bitmap.height)       let wallTexture: Bitmap       let wallX: Double       if end.x.rounded(.down) == end.x       {         wallTexture = textures[.wall]         wallX = end.y - end.y.rounded(.down)       }       else       {         wallTexture = textures[.wall2]         wallX = end.x - end.x.rounded(.down)       }       let textureX = Int(wallX * Double(wallTexture.width))       let wallStart = Vector(x: Double(x), y: (Double(bitmap.height) - height) / 2 - 0.001)       bitmap.drawColumn(textureX, of: wallTexture, at: wallStart, height: height)               // Draw floor       let floorTexture = textures[.floor]       let floorStart = Int(wallStart.y + height) + 1       for y in min(floorStart, bitmap.height) ..< bitmap.height {         let normalizedY = (Double(y) / Double(bitmap.height)) * 2 - 1         let perpendicular = wallHeight * focalLength / normalizedY         let distance = perpendicular * distanceRatio         let mapPosition = ray.origin + ray.direction * distance         let tileX = mapPosition.x.rounded(.down), tileY = mapPosition.y.rounded(.down)         let textureX = Int((mapPosition.x - tileX) * Double(floorTexture.width))         let textureY = Int((mapPosition.y - tileY) * Double(floorTexture.height))         bitmap[x, y] = floorTexture[textureX, textureY]       }       columnPosition += step     }   } } The rest of the code can be found in the link below: https://github.com/KingDecorpel12/RampageFPS/tree/main/RetroRampage/Source Any and all help will be greatly appreciated!
4
0
3.4k
Jun ’21
FPS App crashes when compiling, “Thread 1: Swift runtime failure: Range requires lowerBound <= upperBound” error
In the fps I'm making, I am making a 2D maze for the avatar to navigate in. I just finished coding it however whenever I compile it the app instantly crashes. The error that makes it crash is the following "Thread 1: Swift runtime failure: Range requires lowerBound <= upperBound" and occurs in this file Bitmap.swift import UIKit public struct Bitmap { public private(set) var pixels: [Color] public let width: Int public init(width: Int, pixels: [Color], height: Int) { self.width = width self.pixels = pixels } } public extension Bitmap { var height: Int { let bitmapheight = pixels.count / width return bitmapheight } subscript(x: Int, y: Int) -> Color { get { return pixels[y * width + x] } set { guard x >= 0, y >= 0, x < width, y < height else { return } pixels[y * width + x] = newValue} } init(width: Int, height: Int, color: Color) { self.pixels = Array(repeating: color, count: width * height) self.width = width } mutating func fill(rect: Rect, color: Color) { for y in Int(rect.min.y) ..< Int(rect.max.y) { for x in Int(rect.min.x) ..< Int(rect.max.x) { self[x, y] = color } } } } at the line for x in Int(rect.min.x) ..< Int(rect.max.x) When I put a breakout on the line and run the code I see the following when the compiler runs the line: min Engine.Vector x = (Double) 51.75 y = (Double) 0 max Engine.Vector x = (Double) 2 y = (Double) 51.75 I also get this at the terminal: Engine was compiled with optimization - stepping may behave oddly; variables may not be available. Since it's a big project and there's multiple files calling from one another in both the main game files and the game engine files, you can find the rest of the source code in the link below: https://github.com/KingDecorpel12/RampageFPS Game Engine files, including Bitmap.swift, will be in Rampage/Source/Engine while the main game files will be in Rampage/Source/Rampage. Any and all help will be greatly appreciated!.
1
0
842
Jun ’21
'height' is inaccessible due to 'internal' protection level error
I am coding a basic fps app on Xcode 12.5. As of right now, Im working on a file that acts as a bridge between UIKit and the game engine used for this game. The code is provided below: Bitmap.swift import UIKit public struct Bitmap {   public private(set) var pixels: [Color]   public let width: Int       public init(width: Int, pixels: [Color])   {     self.width = width     self.pixels = pixels   } } public extension Bitmap {   var height: Int   {     return pixels.count / width   }   subscript(x: Int, y: Int) -> Color   {     get { return pixels[y * width + x] }     set { pixels[y * width + x] = newValue}   }   init(width: Int, height: Int, color: Color) {     self.pixels = Array(repeating: color, count: width * height)     self.width = width   } } UIImage+Bitmap.swift import UIKit import Engine extension UIImage {   convenience init?(bitmap: Bitmap) {     let alphaInfo = CGImageAlphaInfo.premultipliedLast     let bytesPerPixel = MemoryLayout<Color>.size     let bytesPerRow = bitmap.width * bytesPerPixel     guard let providerRef = CGDataProvider(data: Data(       bytes: bitmap.pixels, count: bitmap.height * bytesPerRow     ) as CFData) else {       return nil     }     guard let cgImage = CGImage(       width: bitmap.width,       height: bitmap.height,       bitsPerComponent: 8,       bitsPerPixel: bytesPerPixel * 8,       bytesPerRow: bytesPerRow,       space: CGColorSpaceCreateDeviceRGB(),       bitmapInfo: CGBitmapInfo(rawValue: alphaInfo.rawValue),       provider: providerRef,       decode: nil,       shouldInterpolate: true,       intent: .defaultIntent     ) else {       return nil     }     self.init(bitmap: cgImage)   } } For my UIImage+Bitmap.swift code I get the following error: "'height' is inaccessible due to 'internal' protection level" Any help will be appreciated!
7
0
3.6k
Jun ’21
View Details From Search Result Xcode 12.2
I'm working on a simple anime app project where you can view a list of the top anime, search for any anime, add them to either a watched, to watch or watching section as well view the info (such as synopsis for example) when clicking on an anime. For the most part, everything works except for viewing the anime info from the search results, an example being not able to view the info of Naruto when clicking on it in search results. My code is in the attachment below. Continued
0
0
708
May ’21