2016-03-27 15 views
5

Dường như vòng lặp Swift for-in sau đang cố gắng đi qua nhiều phần tử hơn là trong mảng.Vòng lặp for-in đi quá xa và tìm 'nil' trong khi unwrapping

Ví dụ, mã này:

var list:[Int?] = [1,2,3,4,5,6,7] 

print("C-Style for loop") 
for var i=0; i<list.count; i++ 
{ 
    var x:Int = list[i]! 
    print(x) 
} 

print("\nFor-in loop") 
for var x:Int! in list 
{ 
    print(x) 
} 

Gets sản lượng này:

C-Style for loop 
1 
2 
3 
4 
5 
6 
7 

For each loop 
1 
2 
3 
4 
5 
6 
7 
fatal error: unexpectedly found nil while unwrapping an Optional value 
... 
Illegal instruction: 4 

tôi phải mất một cái gì đó ở đây. Không nên list.count là số yếu tố mà vòng lặp for-in cố gắng tháo gỡ?

Không được minh họa ở trên, vòng lặp for-in hoạt động như mong đợi nếu sử dụng danh sách [Int] thay vì [Int?] mà không cần mở khóa.

Tôi đang sử dụng phiên bản Swift 2.1.1.

+0

Một số hành vi kỳ lạ ở đây. Nếu bạn gắn nhãn 'list' là' [Int] 'và sau đó gắn nhãn' x' thành 'Int?', Vòng lặp 'for-in' sẽ in' nil' mãi mãi. – BallpointBen

+0

@Robert Hành vi đó không có gì đặc biệt lạ nếu bạn hiểu cách nó hoạt động ... nhưng Swift có lẽ chỉ đơn giản là ngăn chặn 'x' là nhãn như một tùy chọn như vậy (vì nó chỉ có thể dẫn đến một vòng lặp vô hạn). – nhgrif

+0

Bạn có thể giải thích ngắn gọn những gì đang diễn ra không? Tại sao điều này tạo ra một vòng lặp vô hạn? – BallpointBen

Trả lời

4

Về cơ bản bạn đã làm điều gì đó mà bạn không phải làm, và do đó bạn đã tình cờ gặp một thứ có thể là lỗi trình biên dịch (vì trình biên dịch không ngăn bạn). Rất đẹp!

Bây giờ, giải pháp. Bạn rõ ràng đang cố gắng cởi mở với Int! của mình. Để unwrap an toàn, sử dụng for case cú pháp:

let list:[Int?] = [1,2,3,4,5,6,7] 
for case let x? in list 
{ 
    print(x) // 1, 2, 3, 4, 5, 6, 7 
} 

Một cách khác (cùng kết quả):

let list:[Int?] = [1,2,3,4,5,6,7] 
list.flatMap{$0}.forEach{print($0)} // 1, 2, 3, 4, 5, 6, 7 
+0

Vì vậy, forEach bị cùng một vấn đề ... đáng sợ. – Darko

+0

@ Darko không, nó thực sự không; mang lại cho tôi một giải pháp - đơn giản 'list.forEach {print ($ 0!)} 'công trình (mặc dù tất nhiên nó có khả năng nguy hiểm vì các lý do khác) – matt

+0

Có, nhưng list.forEach {print ($ 0)} cũng bị treo. Sự cần thiết cho flatMap ở đây là đáng sợ với tôi. – Darko

2

Tháo dỡ cưỡng bức như x:Int! là kiểu mã hóa nguy hiểm khi bạn không thể loại trừ số không. Giữ nguyên cho var x:Int = list[i]!.

này hoạt động:

print("\nFor-in loop") 
for x in list { 
    print(x) 
} 

Ở đây bạn cho phép x là con số không và có thể kiểm tra một cách an toàn cho con số không sau.

Bây giờ đến câu hỏi tại sao phá vỡ mã của bạn:

Bên trong, nhanh chóng sử dụng list.generate() cho vòng lặp cho phòng. Máy phát điện không được chấm dứt mà có lẽ là lý do tại sao mã của bạn bị hỏng.

+0

Nhưng vấn đề là điều này mang lại Tùy chọn (1), Tùy chọn (2), v.v., đó không phải là những gì OP muốn. – matt

+0

Bạn chính xác. Tôi nghi ngờ in chỉ để gỡ lỗi và OP rõ ràng là biết làm thế nào để unwrap. Câu hỏi thú vị hơn cho tôi là tại sao nó thất bại. –

Các vấn đề liên quan