Hi guys,
I hope you are doing fine.
I am trying to achieve following thing:
) Fetch data array from database (async call)
) Iterate over fetched data array
) Fetch additional information about each object (async call)
) Create a new data array with all the information and return it back
Currently, I have following approach
self.dataAccessService.fetchRepliesByCommentId(completionHandler: { (commentReplyArray) in
for var i in 0..<commentReplyArray.count {
let commentReply = commentReplyArray[i]
let commentItem = CommentItem()
self.fetchDetailsAboutCommentReply(commentReplyObject: commentReply) { (commentItem) in
commentItem.commentObject = commentReply
dataSource.insert(commentItem, at: index + i + 1) -> APP CRASHES HERE, i is never 0 here
ips.append(IndexPath(row: index + i + 1 , section: 0))
if (i == commentReplyArray.count - 1) {
self.delegate?.didLoadReplies(dataSource: dataSource, ips: ips)
}
}
}
}, commentId: commentItem.commentObject.id)
My fetchDetailsAboutCommentReply function:
private func fetchDetailsAboutCommentReply(commentReplyObject:CommentReply, completionHandler:@escaping(CommentItem)->()) {
let group = DispatchGroup()
let commentItem = CommentItem()
group.enter()
self.dataAccessService.fetchUserById(completionHandler: { (userObject) in
commentItem.userObject = userObject
group.leave()
}, uid: commentReplyObject.userId)
group.enter()
self.dataAccessService.fetchDownloadURLOfProfileImage(organizerId: commentReplyObject.userId) { (contentURL) in
commentItem.userObject.contentURL = contentURL
group.leave()
}
group.notify(queue: .main) {
completionHandler(commentItem)
}
}
My question is how, I can change my code, so the loop basically "pauses" until I fetch every detail information of the iterated object, add it into the dataSource Array and then continues with the next one?
Thanks and stay healthy!
Post
Replies
Boosts
Views
Activity
So the use case I want to do is easy. ) Select a video from library
) Trim video and apply a CIFilter
) Upload it to FireStore
Here is my code:
) Select a video from library
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var image = UIImage()
let applyEffectController = STORYBOARD.instantiateViewController(withIdentifier: "applyEffects") as! ApplyEffectsViewController
if let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String {
if mediaType == "public.image" {
let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
image = pickedImage!
}
if mediaType == "public.movie" {
let videoURL = info[.mediaURL] as! URL
image = AVUtil.createThumbnail(videoURL: videoURL)
let avAsset = AVUtil.trimVideo(videoURL: videoURL)
let fileManager = FileManager.default
let documents = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
try! avAsset.export(to: documents.appendingPathComponent(VIDEO_NAME))
applyEffectController.avAsset = avAsset
applyEffectController.IS_VIDEO_SELECTED = true
}
}
self.dismiss(animated: true, completion: nil)
applyEffectController.challengeImage = image
self.navigationController?.pushViewController(applyEffectController, animated: true)
}
) Trim video and apply a CIFilter
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
var chosenFilter = filterImagesArray[indexPath.row]
chosenFilter = stripFileExtension(chosenFilter)
let contentFilter = CIFilter(name: chosenFilter)
let challengeCIImage = CIImage(image: challengeImage)
contentFilter!.setValue(challengeCIImage, forKey: kCIInputImageKey)
let editedChallengeImage = contentFilter!.value(forKey: kCIOutputImageKey) as! CIImage
challengeImageView.image = UIImage(ciImage: editedChallengeImage)
if (IS_VIDEO_SELECTED) {
playerItem?.videoComposition = AVVideoComposition(asset: avAsset!, applyingCIFiltersWithHandler: { (request) in
let source = request.sourceImage.clampedToExtent()
contentFilter?.setValue(source, forKey: kCIInputImageKey)
_ = CMTimeGetSeconds(request.compositionTime)
let output = contentFilter?.outputImage!.cropped(to: request.sourceImage.extent)
request.finish(with: output!, context: nil)
})
}
}
Confirm filter and redirect to the view controller where I do the upload
@objc func confirmButton_clicked() {
let createChallengeController = STORYBOARD.instantiateViewController(withIdentifier: "createChallenge") as! CreateChallengeViewController
createChallengeController.IS_VIDEO_SELECTED = IS_VIDEO_SELECTED
createChallengeController.challengeImage = challengeImageView.image!
createChallengeController.challengeObject = challengeObject
if (IS_VIDEO_SELECTED) {
let fileManager = FileManager.default
let documents = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
if (fileManager.fileExists(atPath: documents.appendingPathComponent(EDITED_VIDEO_NAME).path)) {
DispatchQueue.main.async(execute: {
try! fileManager.removeItem(atPath: documents.appendingPathComponent(EDITED_VIDEO_NAME).path)
})
}
let videoExport = AVAssetExportSession(asset: (playerItem?.asset)!, presetName: AVAssetExportPresetMediumQuality)
videoExport?.outputFileType = .mov
videoExport?.outputURL = documents.appendingPathComponent(EDITED_VIDEO_NAME)
videoExport?.videoComposition = playerItem?.videoComposition
createChallengeController.challengeImage = self.challengeImageView.image!
print(videoExport?.outputURL)
let group = DispatchGroup()
group.enter()
self.view.addSubview(activityView)
videoExport?.exportAsynchronously(completionHandler: {
createChallengeController.videoURL = videoExport?.outputURL
group.leave()
})
group.notify(queue: .main) {
self.navigationController?.pushViewController(createChallengeController, animated: true)
self.activityView.removeFromSuperview()
}
}
else {
self.navigationController?.pushViewController(createChallengeController, animated: true)
}
}
*3.) Upload it to FireStore
var videoData = NSData()
		do {
				videoData = try NSData(contentsOf: self.videoURL!, options: .dataReadingMapped)
		}
		catch {
				cancelChallenge(challengeId: challengeId) // always goes here -> it fails
				return
		}
The exception I get is:
"The file “editedVideo.mov” couldn’t be opened because there is no such file."
The approach above works with videos which are about 30-35 sec. (without trmming). If I upload a video which is about two minutes, then it always fails.
I need your help. Thank you and stay healthy!
*
Hello everyone,
I have been struggling a lot with this issue:
Using an UITableView, I want to use a custom UITableViewCell which contains labels and an image view.
Depending on how long the text is, which I want to display on the labels, the height of the cell should be adjusted automatically.
Currently, I have this approach in my viewDidLoad method:
activityTableView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(activityTableView)
activityTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
activityTableView.widthAnchor.constraint(equalToConstant: width).isActive = true
activityTableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: height * (60 / IPHONE8_SCREEN_HEIGHT)).isActive = true
activityTableView.heightAnchor.constraint(equalToConstant: height * (554 / IPHONE8_SCREEN_HEIGHT)).isActive = true
//activityTableView.frame = CGRect(x: 0, y: navigationBar.frame.maxY, width: width, height: height * (554 / IPHONE8_SCREEN_HEIGHT))
activityTableView.delegate = self
activityTableView.dataSource = self
activityTableView.register(ActivityTableViewCell.self, forCellReuseIdentifier: "activityCell")
activityTableView.estimatedRowHeight = 92
activityTableView.rowHeight = UITableView.automaticDimension
Furthermore, I have delegates:
extension ActivityViewController:UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
My custom table view cell
func initActivityLabel() {
activityLabel.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(activityLabel)
activityLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 81).isActive = true
activityLabel.widthAnchor.constraint(equalToConstant: cellWidth * (276 / cellWidth)).isActive = true
activityLabel.topAnchor.constraint(greaterThanOrEqualTo: self.contentView.topAnchor, constant: 13).isActive = true
activityLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -38).isActive = true
activityLabel.setColorForLabelTitle()
activityLabel.font = .boldSystemFont(ofSize: LABEL_TEXT_SIZE)
activityLabel.numberOfLines = 0
activityLabel.lineBreakMode = .byWordWrapping
activityLabel.sizeToFit()
}
func initActivityButton() {
self.activityButton.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(activityButton)
activityButton.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 250).isActive = true
activityButton.widthAnchor.constraint(equalToConstant: 131).isActive = true
activityButton.topAnchor.constraint(equalTo:self.activityLabel.bottomAnchor, constant: 0).isActive = true
activityButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
activityButton.addTarget(self, action: #selector(activityButton_clicked), for: .touchDown)
activityButton.setColor()
activityButton.roundCorners()
self.layoutIfNeeded()
}
Those init-functions are called within this method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let activityCell = tableView.dequeueReusableCell(withIdentifier: "activityCell", for: indexPath) as! ActivityTableViewCell
activityCell.selectionStyle = .none
activityCell.sizeToFit()
activityCell.backgroundColor = DARK_BLUE_COLOR
let activityObject = activityArray[indexPath.row]
		 activityCell.initActivityLabel() ..
		
As you can see, everything is done programmatically. I need to do it like this, so I was wondering if you could give me any hints.
When I run the code, the table view doesn't show the label at all. I get a warning regarding a constraint violation. But why?
Hello everyone,
I am currently working on having an application to display comments with respective replies.
I can show all the comments easily in a table view having a simple array of comment objects. In case, one of the comment has any replies (in the database stored), I need to load those replies - which are represented as a different objects at the moment - and display them under the correct comment.
For the table view, this means, new rows are going to be inserted.
I tried to code this but somehow, this ends up in an endless loop. Maybe you guys can give me a hint?
This is my function to load the comments first
func fetchCommentsByParticipationId() {
dataAccessService.fetchCommentsByParticipationId(completionHandler: { (commentArray) in
self.commentArray = commentArray
self.commentTableView.reloadData()
}, participationId: participationObject.id)
}
I have two arrays as data sources. One contains the comments and the other ones contains the comment replies
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return commentArray.count + commentReplyArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let commentsTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentsTableViewCell") as! CommentsTableViewCell
commentsTableViewCell.backgroundColor = DARK_BLUE_COLOR
let cellHeight = commentsTableViewCell.frame.height
let cellWidth = commentsTableViewCell.frame.width
let commentObject = commentArray[indexPath.row] // Comment(json: (hitsTableController.hitsSource?.hit(atIndex: indexPath.row))!)
commentsTableViewCell.initSenderLabel(cellWidth: cellWidth, cellHeight: cellHeight)
commentsTableViewCell.initReplyButton(cellWidth: cellWidth, cellHeight: cellHeight)
dataAccessService.fetchUserById(completionHandler: { (userObject) in
commentsTableViewCell.senderLabel.text = userObject.firstName + " " + userObject.lastName
}, uid: commentObject.userId)
commentsTableViewCell.initCommentLabel(cellWidth: cellWidth, cellHeight: cellHeight)
commentsTableViewCell.commentTextView.text = commentObject.comment
commentsTableViewCell.replyButtonAction = { [unowned self] in
self.commentReplyObject.commentId = commentObject.id
self.commentReplyObject.userId = commentObject.userId
var replyToUserName = commentsTableViewCell.senderLabel.text!
replyToUserName = replyToUserName.replacingOccurrences(of: " ", with: "")
self.replyToUser(replyToUserName: replyToUserName)
}
// fetch replies to comments
dataAccessService.fetchRepliesByCommentId(completionHandler: { (_commentReplyArray) in
for commentReply in _commentReplyArray {
self.commentReplyArray.append(commentReply)
self.commentTableView.insertRows(at: [
(NSIndexPath(row: self.commentArray.count-1, section: 0) as IndexPath)], with: .bottom)
commentsTableViewCell.initReplyViews(cellWidth: cellWidth, cellHeight: cellHeight)
commentsTableViewCell.senderLabel.text = "Test"
commentsTableViewCell.commentTextView.text = commentReply.comment
}
}, commentId: commentObject.id)
return commentsTableViewCell
}
```
What would be the best idea to achieve what I want to do?
I am using the sdk from OneSignal. Let's assume, I have following use case:User A use my app in German language. He triggers an action within the app e. g. a like on an image of User B. User B gets a push notification about the like. But User B uses the app in English language. How can I achieve that?I mean, I can send the notification message in a particular language but if User B decides to change the language of the mobile device to Turkish, then I have to be flexibel.Is there any way, I can access the incoming push notification on the target device?Currently, my code for sending the notification from the source device looks like this:public func notifyAboutSubscription(userObject:User, receiverArray:[String]) {
var receiverArray = removeChallengeCreatorTokenFromArray(receiverArray: receiverArray)
notificationTypeService.clearReceiverListForNotificationType(completionHandler: { (clearedReceiverArray) in
receiverArray = clearedReceiverArray
let source = self.determineUserType(userObject: userObject)
OneSignal.postNotification(["contents": ["en": source
+ NSLocalizedString(FOLLOW_MESSAGE, comment: "")], "include_player_ids": receiverArray])
}, receiverList: receiverArray, notificationType: NotificationType.follow)
}I am thankful for any hintsBest regards,Nazar Medeiros
Hello everyone,I am working with auto layouts for the first time, but I am a but confused. Let me explain you my problem by showing the code I havefunc setupView() {
self.view.translatesAutoresizingMaskIntoConstraints = false
var createdButton = UIButton()
createdButton.setTitle(CREATED_BUTTON_TITLE, for: .normal)
createdButton.setTitleColor(DARK_BLUE_COLOR, for: .normal)
createdButton.backgroundColor = UIColor.white
createdButton.addTarget(self, action: #selector(fetchMyChallenges), for: .touchDown)
createdButton.layer.borderWidth = 1.5
createdButton.layer.borderColor = UIColor.white.cgColor
self.view.addSubview(createdButton)
createdButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
createdButton.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: self.view.frame.width / 3).isActive = true
createdButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 60).isActive = true
createdButton.heightAnchor.constraint(equalTo: self.view.heightAnchor, constant: 54).isActive = true
...So basically, I just want to show a button with some properties set on my view controller. The button appears correctly with the code above, however, the view (self.view) itself is black. I expect it to be black.My questions:1.) Do I always have to set translatesAutoresizingMaskIntoConstraints for super views? Like in this case for self.view?2.) What is actually the correct way of solving it? Is my approach correct? If yes, how I do avoid that black background color?Best regards,Nazar Medeiros
Hi everyone,so I haven't understood one thing:Basically, I don't use the storyboard to create the user interface since for complex UIs like having multiple subviews in one container view etc. using the storyboard is a pain.I am using the good old way with the frames. First I created a template for the iPhone 8 screen using Adobe CC, then I started coding the UI in Xcode by having a look at the frames. For example, I am creating a label like this: ..
let screenSize = UIScreen.main.bounds
let width = screenSize.width
let height = screenSize.height
let accountTypeLabel = UILabel()
accountTypeLabel.frame = CGRect(x: width * (53 / width), y: height * (172 / height), width: width * (269 / width), height: height * (37 / height))
accountTypeLabel.text = ACCOUNT_TYPE_LABEL
accountTypeLabel.textColor = UIColor.white
accountTypeLabel.backgroundColor = DARK_BLUE_COLOR
accountTypeLabel.textAlignment = .center
let accountTypeLabelLabelHeight = accountTypeLabel.frame.size.height
accountTypeLabel.font = UIFont(name: "Kefa", size: accountTypeLabelLabelHeight * (22 / accountTypeLabelLabelHeight))
..Depending on the iPhone device, we have different widths and heights of course. So I just put them into variables and define width and height of my label relatively to the screensize of the corresponding iPhone.Well, this works great for iPhone 8. But I just tried to run the code for the iPhone 8 Plus and here, the label is a little bit more on the left part of the screen, so it doesn't look the same as for iPhone 8.Now my question, why is that the case? Since I am putting the height and width always relatively to the screensize, I would have expected to have some kind of an "autolayout" functionalityCan anyone help?Thanks!
Hi everyone,I bought myself a new notebook. Then I transfered all the data from my previous macbook to the new one by using themigration assistant. After that, I created a new certificate (Apple Push Services) in the Apple developer portal. Using the keychain, I created a certificate signing request on the new mac so this means, I revoked the previous certificate in the developer portal and tried to the enrollment from scratch.Now my actual problem: I downloaded the .cer file. Whenever I do a doubleclick on it, the certificate is not imported into the 'My certificates' section in my keychain tool. But I need to export the p12 file, so how can I do that? The 'My certificates' section is completely empty and I am struggling a lot with this issue.When running Xcode, I get this:CodeSign /Users/nazarmedeiros/Library/Developer/Xcode/DerivedData/Delgado-duyvfumilkktardkhfafnctzmbys/Build/Products/Debug-iphoneos/OneSignalNotificationServiceExtension.appex (in target 'OneSignalNotificationServiceExtension' from project 'Delgado') cd /Users/nazarmedeiros/Desktop/My\ IOS\ Apps/Delgado\ Project/Delgado export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate Signing Identity: "Apple Development: Kaan Cayoglu (KG2HH59QBZ)"Provisioning Profile: "iOS Team Provisioning Profile: *" (35ceee17-9abb-4e81-9fc5-6c69a4f40949) /usr/bin/codesign --force --sign B3B2F1EEA1C3E630DEFF25637172AA73A2944277 --entitlements /Users/nazarmedeiros/Library/Developer/Xcode/DerivedData/Delgado-duyvfumilkktardkhfafnctzmbys/Build/Intermediates.noindex/Delgado.build/Debug-iphoneos/OneSignalNotificationServiceExtension.build/OneSignalNotificationServiceExtension.appex.xcent --timestamp=none /Users/nazarmedeiros/Library/Developer/Xcode/DerivedData/Delgado-duyvfumilkktardkhfafnctzmbys/Build/Products/Debug-iphoneos/OneSignalNotificationServiceExtension.appexI also tried to do couple of other things:- Delete all the files under Library/Keychains- Reset all the keychains- Install Catalina again without deleting existing files- Create a new admin user and try it with itOS version: Catalina, 10.15.2Not sure if issue might be caused because having the keychain in iCloud (just a suggestion)Can anyone help me, please?Thanks
Hi everyone,I bought myself a new notebook. Then I transfered all the data from my previous macbook to the new one by using themigration assistant. After that, I created a new certificate (Apple Push Services) in the Apple developer portal. Using the keychain, I ceated a certificate signing request.Now my actual problem: I downloaded the .cer file. Whenever I do a doubleclick on it, the certificate is not imported into the 'My certificates' section in my keychain tool. But I need to export the p12 file, so how can I do that? The 'My certificates' section is completely empty and I am struggling a lot with this issue.OS version: Catalina, 10.15.2Can anyone help me, please?Thanks
Hi everyone,I have an image view which I initialized using following code:...
imageView.frame = CGRect(x: width * (20 / width), y: navigationBar.frame.maxY, width: width * (335 / width), height: width * (335 / width))
imageView.contentMode = .scaleToFill
imageView.clipsToBounds = true
imageView.isUserInteractionEnabled = true
...As you can see, currently the contentMode is set to .scaleToFill. If I use this setting, most of my image look strange though. The scale seems not to fit somehow. If I change the contentMode to .scaleAspectFill, then every image looks fine.However, for my use case, it is required to use .scaleToFill. What can I do to do that? And why is it acting strange using .scaleToFill?
Hi everyone,when trying to run pod install or pod update, I am getting following problem in the terminal:[!] Couldn't determine repo type for URL: `https://cdn.cocoapods.org/`: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: tlsv1 alert protocol version
[!] Smart quotes were detected and ignored in your Podfile. To avoid issues in the future, you should not use TextEdit for editing it. If you are not using TextEdit, you should turn off smart quotes in your editor of choice.My podfile looks like this:#source 'https://github.com/CocoaPods/Specs.git'
# Uncomment the next line to define a global platform for your project
platform :ios, ’10.0’
target 'Sommerabend' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for Sommerabend
pod 'Firebase/Auth‘
pod 'Firebase/Database’
pod 'Firebase/Storage'
pod 'Firebase/Core'
pod 'Firebase/Firestore'
pod 'Firebase/Messaging'
pod 'AZDropdownMenu'
pod 'Fusuma'
pod 'AlgoliaSearch-Client-Swift', '~> 4.0‘
pod 'SwiftyJSON', '~> 4.0'
pod 'OneSignal', '>= 2.6.2', '< 3.0'
pod 'InstantSearch', '~> 4.0'
target 'OneSignalNotificationServiceExtension' do
pod 'OneSignal', '>= 2.6.2', '< 3.0'
endWhat is the problem? Can anyone help me, please?