I have a UIPageViewControllerDataSource initialised as follows:
[<Register ("FlatImagesPageViewDataSource")>]
type FlatImagesPageViewDataSource() as x =
inherit UIPageViewControllerDataSource()
let mutable isinitialised = false
let mutable flatImages : List<UIImage> = List.Empty
let mutable parentView : UIPageViewController = null
let mutable controllers : List<UIViewController> = List.Empty
let viewControllerAtIndex(index : int) =
let mutable result : UIViewController = null
if flatImages.Length = 0 || index >= flatImages.Length then
result <- null
else
let controller = new FlatImagesContentViewController(new IntPtr())
controller.GetImage <- flatImages.[index]
controller.GetPageIndex <- index
if controllers.Length = 0 then
((controller :> UIViewController )::controllers) |> ignore
int(0) |> ignore
else
let listc = List.toArray controllers
listc.[0] <- (controller :> UIViewController)
controllers <- Array.toList listc
int(0) |> ignore
result <- controller
result
member this.GetParentView
with get() = parentView
and set(value) = (
parentView <- value
controllers <- Array.toList parentView.ViewControllers
)
member this.GetFlatImages
with get() = flatImages
and set(value) = (
flatImages <- value
if not isinitialised then
parentView.View.UserInteractionEnabled <- true
if flatImages.Length > 0 then
let initialcontroller = viewControllerAtIndex(0)
let mutable viewControllers : UIViewController list = []
viewControllers <- initialcontroller::viewControllers
parentView.SetViewControllers(viewControllers |> List.toArray,UIPageViewControllerNavigationDirection.Forward,true,null)
controllers <- viewControllers
isinitialised <- true
else
((controllers.[0]) :?> FlatImagesContentViewController).GetImage <- flatImages.[((parentView.ViewControllers.[0]) :?> FlatImagesContentViewController).GetPageIndex]
)
override x.GetNextViewController(pageViewController : UIPageViewController, contentController : UIViewController) =
let mutable returnController : UIViewController = null
if flatImages.Length > 0 then
let curr_index = (contentController :?> FlatImagesContentViewController).GetPageIndex
Console.WriteLine("Attempting after with index ")
Console.WriteLine(curr_index.ToString())
if curr_index < flatImages.Length - 1 then
returnController <- viewControllerAtIndex(curr_index + 1)
returnController
override x.GetPreviousViewController(pageViewController : UIPageViewController, contentController : UIViewController) =
let mutable returnController : UIViewController = null
if flatImages.Length > 0 then
let curr_index = (contentController :?> FlatImagesContentViewController).GetPageIndex
Console.WriteLine("Attempting before with index ")
Console.WriteLine(curr_index.ToString())
if curr_index > 0 then
returnController <- viewControllerAtIndex(curr_index - 1)
returnController
override x.GetPresentationCount(pageViewController : UIPageViewController) =
Conversions.nint(flatImages.Length)
override x.GetPresentationIndex(pageViewController : UIPageViewController) =
let mutable returnVal = 0
if flatImages.Length > 0 then
returnVal <- (controllers.[0] :?> FlatImagesContentViewController).GetPageIndex
Conversions.nint(returnVal)
This code crashes on the line:
parentView.SetViewControllers(viewControllers |> List.toArray,UIPageViewControllerNavigationDirection.Forward,true,null)
in this code block:
member this.GetFlatImages
with get() = flatImages
and set(value) = (
flatImages <- value
if not isinitialised then
parentView.View.UserInteractionEnabled <- true
if flatImages.Length > 0 then
let initialcontroller = viewControllerAtIndex(0)
let mutable viewControllers : UIViewController list = []
viewControllers <- initialcontroller::viewControllers
parentView.SetViewControllers(viewControllers |> List.toArray,UIPageViewControllerNavigationDirection.Forward,true,null)
controllers <- viewControllers
isinitialised <- true
else
((controllers.[0]) :?> FlatImagesContentViewController).GetImage <- flatImages.[((parentView.ViewControllers.[0]) :?> FlatImagesContentViewController).GetPageIndex]
)
with the following exception:
which I don't understand as I have checked that initialController is definitely not null, therefore I don't understand where this exception is coming from.
I notice when you want to use parentView.SetViewControllers(...) the viewControllers only has one object. How do you construct your UIPageViewController?
If you use UIPageViewControllerSpineLocation.Mid or default UIPageViewControllerSpineLocation(default is Mid), it requires at least two controls when you set its ViewControls.
So you can try to modify initial method like:
new UIPageViewController(UIPageViewControllerTransitionStyle.PageCurl,
UIPageViewControllerNavigationOrientation.Horizontal,
UIPageViewControllerSpineLocation.Min)
Related
I am new to swift.Why the value of a is printed zero here?
var a = 0
var b = 0
let closure = { [a] in
print(a,b)
}
a = 10
b = 10
closure()
This cannot work:
let a () =
async {
return 0
}
let b x =
async {
return
match x with
| true ->
let! y = a() <- you can't compile this
y
| false ->
0
}
I understand I could do this:
let b x =
async {
match x with
| true ->
return! a()
| false ->
return 0
}
but there are cases where I need a:
let! y = a()
to do more operations with the result.
Is there an elegant way to achieve this?
Can't you combine the two?
let b x =
async {
match x with
| true ->
let! y = a()
return y
| false ->
return 0
}
You can move the async expression inside each case:
let b x =
match x with
| true -> async {
let! y = a ()
...
return y
}
| false -> async { return 0 }
I don't know if you think this is more elegant, but more functions usually makes it look a bit nicer, here's an example:
module Async =
let create v = async { return v }
let bind f a = async.Bind (a, f)
let map f a =
bind (f >> create) a
let a () = Async.create 0
let addOne y =
y + 1
let b x =
match x with
| true -> a () |> Async.map addOne
| false -> Async.create 0
// Additional piping to map or bind if you wish, e.g:
// |> Async.bind ...
You can do the return inside the match.
let a () = async {
return 0
}
let b x = async {
match x with
| true -> return! a()
| false -> return 0
}
Otherwise you can do this:
module Async =
let create x = async { return x }
let a () = async {
return 10
}
let b x = async {
let! x1 =
match x with
| true -> a()
| false -> async { return 0 }
let! x2 =
if x then a() else Async.create 0
// Do whatever with x1 or x2
return x2
}
Create a function for code that occur often:
let whatever b a x =
if x then a() else Async.create x
let! y = whatever b a 0
I'm new to Swift and I cannot figure out which optional variable that I unwrapped and I assigned nil to it, I tried to debug it on Playground but it won't let me step through the code.
Fatal error: Unexpectedly found nil while unwrapping an Optional value
public class ListNode {
public var val: Int
public var next: ListNode?
public init() { self.val = 0; self.next = nil; }
public init(_ val: Int) { self.val = val; self.next = nil; }
public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail = result
var carry: Int = 0
var out: Int = 0
var val1: Int = 0
var val2: Int = 0
var head1: ListNode? = l1
var head2: ListNode? = l2
while (l1 != nil || l2 != nil || carry != 0) {
val1 = head1 != nil ? head1!.val : 0
val2 = head2 != nil ? head2!.val : 0
out = (val1 + val2 + carry) % 10
carry = (val1 + val2 + carry) / 10
resultTail.next = ListNode(out)
resultTail = resultTail.next!
head1 = head1?.next!
head2 = head2?.next!
}
return result.next!
}
}
let node3 = ListNode(3)
let node2 = ListNode(4, node3)
let node1 = ListNode(2, node2)
let node3a = ListNode(5)
let node2a = ListNode(6, node3a)
let node1a = ListNode(4, node2a)
let solution = Solution().addTwoNumbers(node1, node1a)
Best regards,
Farros
If you search for the "unexpectedly found nil" error message you will find several questions and answers that explain what this means and suggest debugging techniques.
While the root cause of this error can be subtle, the trigger for the exception is force unwrapping an optional that is nil or referencing an implicitly unwrapped optional that is nil.
You don't have a lot of code here, so it isn't hard to find where you do one of those things;
You force unwrap in your ternary operator, that is after a check for nil, so that won't crash
You force unwrap resultTail.next and result.next but you have assigned values in those cases, so that won't cause the crash.
The last place is where you force unwrap head1.next and head2.next at the bottom of your while loop. This is a mistake because you know that next will eventually be nil at the end of your list.
Simply removing the ! will eliminate the exception, but introduce a new bug because your while loop condition tests the initial parameters l1 and l2 whose values never change. You risk an infinite loop. I think you meant to reference head1 and head2.
You should try and eliminate all force unwraps and this isn't too hard:
Use the nil coalescing operator instead of the ternary
head1 and head2 are optional, so there is no need to force unwrap next
Your function returns an optional, so we can declare resultTail as an optional and use conditional unwrapping or no unwrapping
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail: ListNode? = result
var carry = 0
var head1 = l1
var head2 = l2
while (head1 != nil || head2 != nil || carry != 0) {
let val1 = head1?.val ?? 0
let val2 = head2?.val ?? 0
let sum = val1 + val2 + carry
let out = sum % 10
carry = sum / 10
resultTail?.next = ListNode(out)
resultTail = resultTail?.next
head1 = head1?.next
head2 = head2?.next
}
return result.next
}
}
Note that idiomatic Swift you only explicitly type variables where the correct type cannot be inferred automatically by the compiler or you need a different type to that which the compiler will infer.
You can also simplify and clarify your ListNode by using named parameters with defaults in a single init
public class ListNode {
public var val: Int
public var next: ListNode?
public init(val: Int = 0, next: ListNode? = nil) {
self.val = val
self.next = next
}
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail: ListNode? = result
var carry = 0
var head1 = l1
var head2 = l2
while (head1 != nil || head2 != nil || carry != 0) {
let val1 = head1?.val ?? 0
let val2 = head2?.val ?? 0
let sum = val1 + val2 + carry
let out = sum % 10
carry = sum / 10
resultTail?.next = ListNode(val: out)
resultTail = resultTail?.next
head1 = head1?.next
head2 = head2?.next
}
return result.next
}
}
let node3 = ListNode(val:3)
let node2 = ListNode(val: 4, next: node3)
let node1 = ListNode(val: 2, next: node2)
let node3a = ListNode(val:5)
let node2a = ListNode(val: 6, next: node3a)
let node1a = ListNode(val: 4, next: node2a)
let solution = Solution().addTwoNumbers(node1, node1a)
I am using the map to update all array values. But it's returning an empty array.
var filterProductList = [CategoryProduct]()
let finalList = filterProductList.map{ p in
if let pf = test.rankings[0].products.first(where: {$0.id == p.id}) {
p.rankCount = pf.viewCount
}
}
return finalList // Showing error here cannot convert return expression of type '[()]' to return type '[CategoryProduct]'
You have to explicitly return p and to specify the return type
let finalList = filterProductList.map{ p -> CategoryProduct in
if let pf = test.rankings[0].products.first(where: {$0.id == p.id}) {
p.rankCount = pf.viewCount
}
return p
}
I am trying to implement the sample here with F# and cannot figure out how to correctly override the two overloads "SetBufferContents" in PSHostRawUserInterface:
#r "System.Management.Automation"
open System
open System.Management.Automation.Host
type MyRawUserInterface() =
inherit PSHostRawUserInterface()
override this.BackgroundColor with get() = Console.BackgroundColor and set v = Console.BackgroundColor <- v
override this.BufferSize with get() = Size(Console.BufferWidth, Console.BufferHeight) and set v = Console.SetBufferSize(v.Width, v.Height)
override this.CursorPosition with get() = raise (NotImplementedException()) and set _ = raise (NotImplementedException())
override this.CursorSize with get() = Console.CursorSize and set v = Console.CursorSize <- v
override this.ForegroundColor with get() = Console.ForegroundColor and set v = Console.ForegroundColor <- v
override this.KeyAvailable with get() = Console.KeyAvailable
override this.MaxPhysicalWindowSize with get() = Size(Console.LargestWindowWidth, Console.LargestWindowHeight)
override this.MaxWindowSize with get() = Size(Console.LargestWindowWidth, Console.LargestWindowHeight)
override this.WindowPosition with get() = Coordinates(Console.WindowLeft, Console.WindowTop) and set v = Console.SetWindowPosition(v.X, v.Y)
override this.WindowSize with get() = Size(Console.WindowWidth, Console.WindowHeight) and set v = Console.SetWindowSize(v.Width, v.Height)
override this.WindowTitle with get() = Console.Title and set v = Console.Title <- v
override this.FlushInputBuffer() = ()
override this.GetBufferContents(_) = raise (NotImplementedException())
override this.ReadKey(_) = raise (NotImplementedException())
override this.ScrollBufferContents(_, _, _, _) = raise (NotImplementedException())
override this.SetBufferContents(origin:Coordinates, contents:BufferCell[,]) = raise (NotImplementedException())
override this.SetBufferContents(rectangle:Rectangle, fill:BufferCell) = raise (NotImplementedException())
You need to specify a return type for the function as raise doesn't have a proper return type (it throws an exception).
This is what it should look like
override this.SetBufferContents(origin:Coordinates, contents:BufferCell[,]) : unit = raise (NotImplementedException())