Change camera on opentok for ios - ios

I am trying to change the camera of the publisher in OpenTok. In Android it is super easy, but I don't understand how to do it in objective c for ios.
I tried :
if (_publisher.cameraPosition == AVCaptureDevicePositionFront)
{
_publisher.cameraPosition = AVCaptureDevicePositionBack; // back camera
} else
{
_publisher.cameraPosition = AVCaptureDevicePositionFront; // front camera
}
I have to say that I am a beginner in objective c (and in OpenTok).
How should I do?
Thank you :)

Try this one:
func setCameraPosition(_ position: AVCaptureDevicePosition) -> Bool {
guard let preset = captureSession?.sessionPreset else {
return false
}
let newVideoInput: AVCaptureDeviceInput? = {
do {
if position == AVCaptureDevicePosition.back {
return try AVCaptureDeviceInput.init(device: backFacingCamera())
} else if position == AVCaptureDevicePosition.front {
return try AVCaptureDeviceInput.init(device: frontFacingCamera())
} else {
return nil
}
} catch {
return nil
}
}()
guard let newInput = newVideoInput else {
return false
}
var success = true
captureQueue.sync {
captureSession?.beginConfiguration()
captureSession?.removeInput(videoInput)
if captureSession?.canAddInput(newInput) ?? false {
captureSession?.addInput(newInput)
videoInput = newInput
} else {
success = false
captureSession?.addInput(videoInput)
}
captureSession?.commitConfiguration()
}
if success {
capturePreset = preset
}
return success
}
func toggleCameraPosition() -> Bool {
guard hasMultipleCameras else {
return false
}
if videoInput?.device.position == .front {
return setCameraPosition(.back)
} else {
return setCameraPosition(.front)
}
}

For Swift 4
if(publisher.cameraPosition == .back)
{
publisher.cameraPosition = .front
}else{
publisher.cameraPosition = .back
}
I haven't checked for Objective C but it will be same like

Related

Swift: Using try? to catch Index out of range

so i am making game and there is a grid and you can only place if any of the adjacent blocks are a source block, well if you are trying to place a block in the top grid there's no block above it so an Index out of range error will be thrown. I am trying to catch it but xcode seems to think no error is possible. Am i doing this wrong? I guess I could go to each case and add a catch but I feel like this should work.
copy friendly text if you would like to try it out in your own IDE:
func isValidPlacement(row:Int,col:Int) -> Bool {
if let t = try? tiles[row-1][col], t.isSource {
return true
}
else if let t = try? tiles[row][col-1], t.isSource {
return true
}
else if let t = try? tiles[row+1][col], t.isSource {
return true
}
else if let t = try? tiles[row][col+1], t.isSource {
return true
}
else {
return false
}
}
Runtime errors and returning bools is the Objective-C way! Throw throw throw! 🙀
public extension Collection {
/// - Returns: same as subscript, if index is in bounds
/// - Throws: CollectionIndexingError
func element(at index: Index) throws -> Element {
guard indices.contains(index)
else { throw CollectionIndexingError() }
return self[index]
}
}
extension Collection where Element: Collection {
/// - Returns: same as subscripting, if indices are in bounds
/// - Throws: CollectionIndexingError
func element( at indices: (Index, Element.Index) ) throws -> Element.Element {
try element(at: indices.0).element(at: indices.1)
}
}
/// Thrown when `getElement` is called with an invalid index.
public struct CollectionIndexingError: Error { }
extension Tile {
enum PlacementError: Error {
case invalid
case noSources
}
}
extension Collection where
Index == Int,
Element: Collection, Element.Index == Int, Element.Element == Tile
{
func validatePlacement(row: Index, column: Element.Index) throws {
let tiles = [(-1, 0), (0, -1), (1, 0), (0, 1)].compactMap {
try? element( at: (row + $0.0, column + $0.1) )
}
guard !tiles.isEmpty
else { throw Tile.PlacementError.invalid }
guard tiles.contains(where: \.isSource)
else { throw Tile.PlacementError.noSources }
}
}
In Swift. you can only catch instances of Error that are thrown by code, you can't catch runtime exceptions such as an array bounds violation
You can create your own safeAccess function. You don't say what type is in your array so I will use SomeType as an example
func safeAccess(row:Int, col:Int) -> SomeType? {
guard row >= 0, row < tiles.count else {
return nil
}
guard col >= 0, col < tiles[row].count else {
return nil
}
return tiles[row][col]
}
func isValidPlacement(row:Int,col:Int) -> Bool {
if let t = tiles.safeAccess(row:row-1,col:col), t.isSource {
return true
}
if let t = tiles.safeAccess(row:row,col:col-1),, t.isSource {
return true
}
if let t = tiles.safeAccess(row:row+1,col:col), t.isSource {
return true
}
if let t = tiles.safeAccess(row:row,col:col+1), t.isSource {
return true
}
return false
}
You could also define an extension on Array
extension Array {
func element(at index: Int) -> Element? {
if index >= 0 && index < self.count {
return self[index]
}
return nil
}
}
And to use it:
func isValidPlacement(row:Int,col:Int) -> Bool {
if let tiles = tiles.element(at:row-1), let t = tiles.element(at:col), t.isSource {
return true
}
else if tiles.element(at:row), let t = tiles.element(at:col-1), t.isSource {
return true
}
else if let tiles = tiles.element(at:row+1), let t = tiles.element(at:col), t.isSource {
return true
}
else if let tiles = tiles.element(at:row), let t = tiles.element(at:col+1), t.isSource {
return true
}
else {
return false
}
}
Accessing an index of an array which doesn't exist results in a run time exception. You can't use try here because the array is not throwing anything.
Try adding these two lines at the start of the func and get rid of all of try?
guard row <= tiles.count - 1 else {
return false
}
guard col <= tiles[row].count - 1 else {
return false
}
Also i am assuming, whatever the type array stores here is an optional. if not you can remove if lets too
func isValidPlacement(row:Int,col:Int) -> Bool {
guard row <= tiles.count - 1 else {
return false
}
guard col <= tiles[row].count - 1 else {
return false
}
if let t = tiles[row-1][col], t.isSource {
return true
}
else if let t = tiles[row][col-1], t.isSource {
return true
}
else if let t = tiles[row+1][col], t.isSource {
return true
}
else if let t = tiles[row][col+1], t.isSource {
return true
}
else {
return false
}
}

Completion block never gets called?

We have a function that when it finishes another function should be called in it's completion block but whatever is inside the completion block is never called. Here is the function:
func appendAllData (completion: () -> Void) {
guard let movieDetails = self.movieDetailsData else {
// handle nil case
return;
}
if let posterImage = self.movieDetailsData?.poster {
self.posterArray.append(posterImage)
}
if let overview = self.movieDetailsData?.overview {
self.overviewArray.append(overview)
}
if let releaseDate = self.movieDetailsData?.releaseData {
self.releaseInfoArray.append(releaseDate)
}
if let runtime = self.movieDetailsData?.runtime {
self.releaseInfoArray.append(String(describing: runtime))
}
if let genre = self.movieDetailsData?.genre {
if !genre.isEmpty {
self.releaseInfoArray.append(genre[0].name)
}
}
if let budget = self.movieDetailsData?.budget {
self.boxOfficeArray.append(budget)
}
if let revenue = self.movieDetailsData?.revenue {
self.boxOfficeArray.append(revenue)
}
if let homepage = self.movieDetailsData?.homepage {
self.homePageArray.append(homepage)
}
if let images = self.movieDetailsData?.images {
self.imageArray += images.backdropImages.map{ $0.filePath }
}
}
Here is how it's used:
self.appendAllData(completion: { _ in
//Nothing inside here gets called
DispatchQueue.main.async {
print(self.movieDetailsData?.poster )
if let bgImage = self.movieDetailsData?.poster {
self.backgroundImage.sd_setImage(with: URL(string:"\(baseImageURL)\(bgImage)"))
print("background pic loaded")
self.backgroundImage.addBlurEffect()
}
self.detailTableView.reloadData()
}
})
Nothing inside the completion block is called, any idea how to fix this?
I believe you need to call the completion() at the end for it execute your completion code.
func appendAllData (completion: () -> Void) {
guard let movieDetails = self.movieDetailsData else {
// handle nil case
return;
}
if let posterImage = self.movieDetailsData?.poster {
self.posterArray.append(posterImage)
}
if let overview = self.movieDetailsData?.overview {
self.overviewArray.append(overview)
}
if let releaseDate = self.movieDetailsData?.releaseData {
self.releaseInfoArray.append(releaseDate)
}
if let runtime = self.movieDetailsData?.runtime {
self.releaseInfoArray.append(String(describing: runtime))
}
if let genre = self.movieDetailsData?.genre {
if !genre.isEmpty {
self.releaseInfoArray.append(genre[0].name)
}
}
if let budget = self.movieDetailsData?.budget {
self.boxOfficeArray.append(budget)
}
if let revenue = self.movieDetailsData?.revenue {
self.boxOfficeArray.append(revenue)
}
if let homepage = self.movieDetailsData?.homepage {
self.homePageArray.append(homepage)
}
if let images = self.movieDetailsData?.images {
self.imageArray += images.backdropImages.map{ $0.filePath }
}
completion()
}

How do I know that the contacts have been modified, if the application was not active on iOS?

I need to run a function when the contacts have changed. If the application is active, you can do this with NotificationCenter as narrated in this post (sometimes It works when I add a new number to an existing contact). How do I know that the contact (or contacts) have been changed after the launch of the application?
I made the following functions for my task
#objc private func matchingContacts() {
if isSuccessContactUploading {
contactManager.matchingContacts(notMatch: { [weak self] in
guard let _self = self else { return }
debugPrint("matchingContacts != equals")
_self.isSuccessContactUploading = false
_self.syncContacts()
})
}
}
These functions are in ContactManager
func matchingContacts(notMatch: (() -> Void)?) {
getContacts { (contacts, error) in
if error == nil {
debugPrint("contacts count", contacts.count)
self.getContactsDictionaryFromCache(contacts, notMatch: {
notMatch?()
})
}
}
}
private func getContactsDictionaryFromCache(_ contacts: [CNContact], notMatch: (() -> Void)?) {
var isMatching = true
for contact in contacts {
let key = contact.identifier
do {
let cache = try Cache<NSDictionary>(name: "Contacts")
if let contactDictionary = cache[key] {
if !contactDictionary.isEqual(to: contact.dictionary) {
debugPrint("contactDictionary not matching")
isMatching = false
}
} else {
debugPrint("contactDictionary isn't here")
isMatching = false
}
} catch {
debugPrint(error.localizedDescription)
isMatching = false
}
}
if !isMatching {
notMatch?()
}
cacheContacts(contacts)
}
private func cacheContacts(_ contacts: [CNContact]) {
for contact in contacts {
let contactDictionary = contact.dictionary as NSDictionary
let key = contact.identifier
do {
let cache = try Cache<NSDictionary>(name: "Contacts")
cache[key] = contactDictionary
} catch {
debugPrint(error.localizedDescription)
}
}
}

iOS torchActive always return false

I want to test the torch, so I write some code
guard let camera = camera else {
return
}
if camera.hasTorch {
do {
try camera.lockForConfiguration()
if camera.torchActive {
if camera.isTorchModeSupported(.Off) {
camera.torchMode = .Off
}
} else {
if camera.isTorchModeSupported(.On) {
camera.torchMode = .On
}
}
camera.unlockForConfiguration()
} catch {
}
}
and the camera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) which is a member variable. Like this private var camera: AVCaptureDevice?
The question is I only can make the torchMode = .On, because the torchActive always return flase!!

Return statement in nested if function

I have been struggling with something for a while.
How can I return something in a nested if function?
The function below has the task of finding out if the userProfile has a verified card or not, if verified == 1 (true) then return true, else return false.
func userHasVerfifiedCard() -> Bool{
let userDocument = users.documentWithID(Meteor.userID!)
if let card = userDocument.valueForKey("profile")!["card"] {
print("has card")
if let verified = card!["verified"] as? Int {
print("card.verified as Int")
if verified == 1{
print("card.verified == 1")
lastFourCreditCardLbl.text = card!["last4"] as? String
return true
}else {
return false
}
}
}
your method won't return anything, if if let card won't work. But it must return a bool in any case.
func userHasVerfifiedCard() -> Bool {
let userDocument = users.documentWithID(Meteor.userID!)
if let card = userDocument.valueForKey("profile")!["card"] {
print("has card")
if let verified = card!["verified"] as? Int {
print("card.verified as Int")
if verified == 1 {
print("card.verified == 1")
lastFourCreditCardLbl.text = card!["last4"] as? String
return true
}
}
}
return false
}
Try this and let me know if it's helps..!
func userHasVerfifiedCard() -> Bool{
let userDocument = users.documentWithID(Meteor.userID!)
if let card = userDocument.valueForKey("profile")!["card"], verified = card!["verified"] as? Int where verified == 1 {
return true
} else {
return false
}
}

Resources