Вы должны поймать исключение до того, как выйдет из лямбда:
s = s.filter(a -> { try { return a.isActive(); }
catch (IOException e) { throw new UncheckedIOException(e); }}});
. Рассмотрите тот факт, что лямбда не оценивается в месте, где вы ее пишете, но при некоторые совершенно несвязанные места, в классе JDK. Таким образом, это будет точка, в которой это исключенное исключение будет выбрано, и в этом месте оно не будет объявлено.
Вы можете справиться с этим, используя обертку вашей лямбды, которая переводит проверенные исключения на непроверенные :
public static <T> T uncheckCall(Callable<T> callable) {
try { return callable.call(); }
catch (RuntimeException e) { throw e; }
catch (Exception e) { throw new RuntimeException(e); }
}
Ваш пример будет написан как
return s.filter(a -> uncheckCall(a::isActive))
.map(Account::getNumber)
.collect(toSet());
В моих проектах я рассматриваю этот вопрос без обертывания; вместо этого я использую метод, который эффективно устраняет проверку исключения компилятором. Излишне говорить, что с этим следует обращаться с осторожностью, и все участники проекта должны знать, что проверенное исключение может появиться там, где оно не объявлено. Это код сантехники:
public static <T> T uncheckCall(Callable<T> callable) {
try { return callable.call(); }
catch (Exception e) { return sneakyThrow(e); }
}
public static void uncheckRun(RunnableExc r) {
try { r.run(); } catch (Exception e) { sneakyThrow(e); }
}
public interface RunnableExc { void run() throws Exception; }
@SuppressWarnings("unchecked")
private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
, и вы можете ожидать получить IOException
, брошенное вам в лицо, даже если collect
не объявляет об этом. В большинстве случаев , но не во всех случаях , которые вы хотели бы просто перестроить исключение, и обрабатывать его как общий сбой. Во всех этих случаях ничто не теряется в ясности или правильности. Просто остерегайтесь тех других случаев, когда вы действительно хотите реагировать на исключение на месте. Разработчик не узнает компилятором, что есть IOException
, чтобы поймать там, и компилятор действительно будет жаловаться, если вы попытаетесь его поймать, потому что мы обманули его, полагая, что такое исключение не может быть выброшено.
Если они только белые и черные, было бы намного проще использовать UIView
и установить его backgroundColor
на .white
или .black
. Вы можете использовать свойство tag
для UIView
s, чтобы идентифицировать их.
В вашем обработчике gestureRecognizer recognizer.view
сообщает вам view
, который вызвал жест.
Вы можете назначить теги в Interface Builder . Например, если у вас есть квадрат квадратов 8x8, вы можете использовать двузначное число, где первая цифра - это строка, а вторая цифра - столбец. Таким образом, ваши теги будут 11
, 12
, ..., 87
, 88
.
func squareTapped(recognizer: UIGestureRecognizer) {
if let view = recognizer.view {
let tag = view.tag
let row = tag / 10
let col = tag % 10
print("The view at row \(row), column \(col) was tapped")
if view.backgroundColor == .black {
view.backgroundColor = .white
} else {
view.backgroundColor = .black
}
}
}
Если вы хотите использовать изображения, загрузите изображения как свойства вашего viewController и назначить их на основе строки и столбца вашего изображения. Здесь я использовал сборку Outlet Collection , чтобы удерживать все UIImageView
s. В Interface Builder вы связываете каждую из своих ячеек с свойством squares
.
class BoardViewController: UIViewController {
let blackImage = UIImage(named: "blackImage")!
let whiteImage = UIImage(named: "whiteImage")!
@IBOutlet var squares: [UIImageView]!
var recognizersAdded = false
func setUpBoard() {
for imageview in squares {
if !recognizersAdded {
let recognizer = UITapGestureRecognizer(target: self, action: #selector(squareTapped))
imageview.addGestureRecognizer(recognizer)
imageview.isUserInteractionEnabled = true
}
let tag = view.tag
let row = tag / 10
let col = tag % 10
// Just for demo purposes, set up a checkerboard pattern
if (row + col) % 2 == 0 {
imageview.image = blackImage
} else {
imageview.image = whiteImage
}
}
recognizersAdded = true
}
func squareTapped(recognizer: UIGestureRecognizer) {
if let view = recognizer.view as? UIImageView {
let tag = view.tag
let row = tag / 10
let col = tag % 10
print("The view at row \(row), column \(col) was tapped")
if view.image == blackImage {
view.image = whiteImage
} else {
view.image = blackImage
}
}
}
}
Я добавил добавление PanGestureRecognizer в mainStackView, и я использую эту функцию с hitTest, чтобы узнать, какое представление должно изменить цвет.
func pan(_ recognizer: UIPanGestureRecognizer){
if (recognizer.state == .began ||
recognizer.state == .changed)
{
let loc = recognizer.location(in: principalRowStack)
let view = principalRowStack.hitTest(loc, with: UIEvent())
view?.backgroundColor = .black
}
}
Присвойте тег каждому типу UIImageView и Add Tap.
После нажатия на любом представлении вы можете получить изображение, которое будет выглядеть:
UIImageView * imageView = gestureRecogniser .view